diff --git a/doc/cmdref.sgm b/doc/cmdref.sgm
index 4787a13..530ab48 100644
--- a/doc/cmdref.sgm
+++ b/doc/cmdref.sgm
@@ -403,6 +403,39 @@
are seperated by comments.
+
+
+ .cbmfloatstring
+ [ , string, ... ]: Specifies a
+ series of strings, which are interpreted as floating
+ point constants, and then included in the 5-byte floating
+ point format used by the Commodore BASICs. This format is
+ 8 bits of exponent, followed by a sign bit and a 31-bit
+ big-endian mantissa fraction. (The 1 in front of the
+ binary point is presumed to be present.) An exponent of 0
+ specifies a constant of 0, and the exponent is shifted up
+ by 129 before being stored.
+
+
+ Because IEEE-754 doesn't perfectly match the Commodore's
+ system, if you wish to precisely replicate individual
+ constants that cannot be represented exactly you may have
+ better luck with the following program, which will run on
+ both the Commodore 64 and VIC-20:
+
+
+10 CLR:V=0:PV=PEEK(45)+256*PEEK(46)+2
+20 INPUT "NUMBER (0 TO QUIT)";V
+30 IF V=0 THEN END
+40 PRINT ".BYTE";
+50 FOR I=0 TO 4
+60 IF I>0 THEN PRINT CHR$(157);",";
+70 PRINT PEEK(PV+I);:NEXT I:PRINT:GOTO 20
+
+ This program will print out
+ a .byte directive for you to include in
+ your program to represent that number.
+ .checkpcaddress:
diff --git a/doc/ophismanual.pdf b/doc/ophismanual.pdf
index 1b50fc7..0f58bad 100644
Binary files a/doc/ophismanual.pdf and b/doc/ophismanual.pdf differ
diff --git a/doc/ophismanual.sgm b/doc/ophismanual.sgm
index 46478f5..c251529 100644
--- a/doc/ophismanual.sgm
+++ b/doc/ophismanual.sgm
@@ -6,6 +6,7 @@
+
@@ -42,6 +43,7 @@
&part5;
&part6;
&part7;
+ &part8;
To HLL and Back
diff --git a/doc/preface.sgm b/doc/preface.sgm
index e3b52eb..bda7791 100644
--- a/doc/preface.sgm
+++ b/doc/preface.sgm
@@ -5,8 +5,8 @@
chip used in the vast majority of the classic 8-bit computers and
consoles. Its primary design goals are code readability and output
flexibility - Ophis has successfully been used to create programs
- for the Nintendo Entertainment System, the Atari 2600, and the
- Commodore 64.
+ for the Nintendo Entertainment System, the Atari 2600, and various
+ 8-bit Commodore machines.
Ophis's syntax is noticably different from the formats
@@ -66,6 +66,12 @@
and to become better able to interoperate with other
toolchains. It was this process that led to Ophis 2.
+
+ After its release Ophis 2 was picked up by a number of
+ developers work with actual hardware from the period, including
+ prototype machines that never saw production. Some of their
+ contributions have refined the code generators for version 2.1.
+
This is an updated edition of Programming With
Ophis, including documentation for all new features
@@ -114,7 +120,10 @@
About the examples
- Versions of the examples in this book are available from the Ophis site. Windows users will find them packaged with the distribution; all other users can get them as a separate download or pull them directly from github.
+ Versions of the examples in this book are available from the
+ Ophis site. Windows users will find them packaged with the
+ distribution; all other users can get them as a separate
+ download or pull them directly from github.
The code in this book is available in
diff --git a/doc/samplecode.sgm b/doc/samplecode.sgm
index 26c283d..b8b0120 100644
--- a/doc/samplecode.sgm
+++ b/doc/samplecode.sgm
@@ -606,71 +606,6 @@ _done: rts
.checkpc $A000
.data
.checkpc $D000
-
-
-
- c64_0.oph
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; Commodore 64 Basic Runtime File
-;;
-;; Include this at the TOP of your C64 program, and it will handle
-;; hiding away the BASIC ROM and data and restoring it at the end.
-;;
-;; You will have a contiguous block of RAM from $0800 to $CF81, and
-;; Zero Page access from $02 to $7F in the segment "zp".
-
-.word $0801
-.org $0801
-
-; BASIC program that just calls our machine language code
-.scope
- .word _next, 10 ; Next line and current line number
- .byte $9e," 2062",0 ; SYS 2062
-_next: .word 0 ; End of program
-.scend
-
-.data zp ; Zero Page memory segment.
-.org $0002
-
-.text
-
-.scope
- ; Cache BASIC zero page at top of available RAM
- ldx #$7E
-* lda $01, x
- sta $CF81, x
- dex
- bne -
-
- ; Swap out the BASIC ROM for RAM
- lda $01
- and #$fe
- ora #$06
- sta $01
-
- ; Run the real program
- jsr _main
-
- ; Restore BASIC ROM
- lda $01
- ora #$07
- sta $01
-
- ; Restore BASIC zero page
- ldx #$7E
-* lda $CF81, x
- sta $01, x
- dex
- bne -
-
- ; Back to BASIC
- rts
-
-_main:
- ; Program follows...
-.scend
diff --git a/doc/tutor1.sgm b/doc/tutor1.sgm
index 04c5295..4bfb9be 100644
--- a/doc/tutor1.sgm
+++ b/doc/tutor1.sgm
@@ -296,8 +296,11 @@ hello: .byte "HELLO, WORLD!", 0
Overrides the default filename for output.
+ Specifies an optional listing file that gives the emitted binary in human-readable form, with disassembly.
+ Specifies an optional map file that gives the in-source names for every label used in the program.Allows the 6510 undocumented opcodes as listed in the VICE documentation.Allows opcodes and addressing modes added by the 65C02.
+ Allows opcodes and addressing modes added by the 4502. (Experimental.)Quiet operation. Only reports warnings and errors.Verbose operation. Reports files as they are loaded.
@@ -315,14 +318,16 @@ Loading hello1.oph
Assembly complete: 45 bytes output (14 code, 29 data, 2 filler)
- This will produce a file named hello.prg. If
- your emulator can run PRG files directly,
- this file will now run (and print HELLO,
- WORLD!) as many times as you
- type RUN. Otherwise, use
- a D64 management utility to put
- the PRG on a D64, then
- load and run the file off that.
+ This will produce a file
+ named hello.prg. If your emulator can
+ run PRG files directly, this file will now
+ run (and print HELLO, WORLD!)
+ as many times as you type RUN.
+ Otherwise, use a D64 management utility to
+ put the PRG on a D64,
+ then load and run the file off that. If you have access to a
+ device like the 1541 Ultimate II, you can even load the file
+ directly into the actual hardware.
diff --git a/doc/tutor2.sgm b/doc/tutor2.sgm
index c0128ef..806246b 100644
--- a/doc/tutor2.sgm
+++ b/doc/tutor2.sgm
@@ -43,6 +43,13 @@ _next: .word 0 ; End of program
.advance 2064
+
+ It's possible to have multiple temporary labels with the same
+ name in different parts of the code. If you create a label map
+ in those cases, you will have to look at the sourcefile location
+ to distinguish them.
+
+
Anonymous labels
diff --git a/doc/tutor3.sgm b/doc/tutor3.sgm
index 25dd6bc..5b59323 100644
--- a/doc/tutor3.sgm
+++ b/doc/tutor3.sgm
@@ -100,7 +100,9 @@
No global or anonymous labels may be defined inside a macro:
temporary labels only persist in the macro expansion itself.
- (Each macro body has its own scope.)
+ (Each macro body has its own scope. A label map will trace
+ back through macro expansions to describe were a label inside
+ a macro body came from.)
diff --git a/doc/tutor6.sgm b/doc/tutor6.sgm
index df527c3..c4f048b 100644
--- a/doc/tutor6.sgm
+++ b/doc/tutor6.sgm
@@ -79,7 +79,10 @@ _done: rts
Note that we only have to name cache once, but
- can use addition to refer to any offset from it.
+ can use addition to refer to any offset from it.We
+ could spare ourselves some trouble here and use $fb instead of
+ $10, which BASIC does not use, but the
+ example is more thorough this way.
diff --git a/doc/tutor7.sgm b/doc/tutor7.sgm
index 49ec6bc..f8e7e51 100644
--- a/doc/tutor7.sgm
+++ b/doc/tutor7.sgm
@@ -2,11 +2,11 @@
Advanced Memory Segments
- This is the last section of the Ophis tutorial. By now we've
- covered the basics of every command in the assembler; in this
- final installment we show the full capabilities of
+ By now we've covered the basics of every command in the assembler;
+ in this final installment we show the full capabilities of
the .text and .data commands
- as we produce a final set of Commodore 64 header files.
+ as we produce a more sophisticated set of Commodore 64 header
+ files.
@@ -45,9 +45,9 @@
Now, actually, the rest of the zero page is reserved too:
- locations $02-$7F are used by the BASIC interpreter, and
- locations $80-$FF are used by the KERNAL. We don't need the
- BASIC interpreter, though, so we can back up all of $02-$7F at
+ locations $02-$8F are used by the BASIC interpreter, and
+ locations $90-$FF are used by the KERNAL. We don't need the
+ BASIC interpreter, though, so we can back up all of $02-$8F at
the start of our program and restore it all when we're done.
@@ -60,9 +60,9 @@
.scope
; Cache BASIC zero page at top of available RAM
- ldx #$7E
+ ldx #$8e
* lda $01, x
- sta $CF81, x
+ sta $cf81, x
dex
bne -
@@ -81,8 +81,8 @@
sta $01
; Restore BASIC zero page
- ldx #$7E
-* lda $CF81, x
+ ldx #$8e
+* lda $cf81, x
sta $01, x
dex
bne -
@@ -96,13 +96,6 @@ _main:
.scend
-
- The new, improved header file is . This,
- like c64kernal.oph, is available for use in
- your own projects in the platform/ directory.
-
-
Our print'str routine is then rewritten to
declare and use a zero-page variable, like so:
@@ -141,24 +134,8 @@ _done: rts
- That concludes our tour. The final source file
- is .
-
-
-
- Where to go from here
-
- This tutorial has touched on everything that the assembler can
- do, but it's not really well organized as a
- reference. is a better place to look
- up matters of syntax or consult lists of available commands.
-
-
- If you're looking for projects to undertake, the Commodore 64
- and Atari 2600 development communities are both very strong, and
- the Apple II and NES development communities are still alive and
- well as well. There's an annual Minigame Competition that's
- always looking for new entries.
+ The final source file is .
diff --git a/doc/tutor8.sgm b/doc/tutor8.sgm
new file mode 100644
index 0000000..7ff3b9e
--- /dev/null
+++ b/doc/tutor8.sgm
@@ -0,0 +1,211 @@
+
+ Platform-Specific Techniques
+
+
+ Ophis is intended to produce cross-assembled binaries that will
+ run in a variety of contexts. The expectation is that most users
+ will be writing for emulated versions of hardware from when the
+ 6502 chip was current, and producing files either for those
+ emulators or for devices that will transfer the results to real
+ hardware. This chapter describes the support routines and examples
+ to make those tasks easier.
+
+
+
+ The Commodore 64 and VIC-20
+
+
+ In a real sense, the Commodore 64 is the "native"
+ target platform for Ophis. It was the first platform targeted
+ and it's the one that has received the most additional
+ support. It's also one where the developer needs to take the
+ most care about exactly what kind of program they are
+ writing.
+
+
+
+
+
+ c64kernal.oph actually defines no
+ code. It merely sets up the customary names for the KERNAL
+ jump table routines so that you may refer to routines
+ like chrout and rdtim
+ by name.
+
+
+
+
+ c64header.oph is an absolutely minimal
+ C64 header program; it contains the one-line BASIC program
+ and nothing else. Smaller programs that do not require more
+ than four bytes of zero page do not need to do any
+ bankswitching or zero page caching and don't need any more
+ than this. The aliases provided
+ in c64kernal.oph may be useful, but are
+ not included in this header.
+
+
+
+
+ c64_0.oph is suitable for larger and more
+ sophisticated programs. It is an enhancement of the header
+ file developed in the previous chapter. It stores the saved
+ zero page values in the RAM shadowed by the KERNAL ROM, and
+ it also uses a different mechanism for returning to BASIC
+ when done that is more robust in the face of self-modifying
+ programs such as those produced by self-extracting
+ compressed executables or onefiled multipart programs. It is
+ used like the other header files—just include it at
+ the top of your source file and use RTS
+ to end your program—but programs that use this header
+ file will have all of the zero page from $02-$8F and a
+ contiguous chunk of program RAM from $0800-$CFFF.
+
+
+
+
+ libbasic64.oph is an experimental set of
+ macros and routines to permit the assembly programmer to
+ make use of the software floating point routines provided by
+ BASIC. It is, for obvious reasons, not compatible
+ with c64_0.oph, because it needs to make
+ use of BASIC's workspace and the ROM itself. If you wish to
+ use this file you should include it near the end of your
+ program.
+
+
+
+
+ vic20.oph is a header that will work for
+ the unexpanded VIC-20. Memory expansion
+ slots change where BASIC programs load, and since these
+ headers load in the machine language program in as the
+ suffix to a BASIC program, that also changes where they are
+ themselves loaded. There is no trickery with bankswitching
+ ROMs in and out—the VIC-20 does not have enough RAM to
+ gain anything from these techniques.
+
+
+
+
+ vic20x.oph does the same, but for a
+ VIC-20 with one or more memory expansions.
+
+
+
+
+
+ Using LIBBASIC64
+
+
+ The 6502's arithmetic capabilities are rather limited. To
+ counteract this, BASICs of the era did floating point in
+ software and gave BASIC programmers the full suite of
+ arithmetic operations. These operations are largely
+ unavailable to machine language programmers.
+
+
+
+ The libbasic64.oph library is an attempt to
+ address this. It is currently considered highly experimental,
+ but initial results are very promising.
+
+
+
+ BASIC stores floating point numbers in a five-byte format, but
+ translates them into a seven-byte format to do actual work in
+ two Floating Point Accumulators (FAC1 and FAC2). Ophis will
+ let you specify 5-byte constants with
+ the .cbmfloat directive, which takes a
+ string and produces the requisite five-byte value.
+
+
+
+ The floating point functions in BASIC all operate on FAC1 and
+ are relatively reliable. The
+ functions abs_fac1, atn_fac1, cos_fac1, exp_fac1, int_fac1, log_fac1, rnd_fac1, sgn_fac1, sin_fac1,
+ and tan_fac1 are all provided. Routines
+ that touch the FACs tend to be extremely finicky. This system
+ defines a set of macros and routines to manage that for you:
+
+
+
+ `f_movedest, source: Copy a five-byte floating point value from source to dest.
+ `fp_loadsrc: Loads FAC1 with the floating point constant specified by src.
+ `fp_storedest: Saves the value of FAC1 to the named memory location.
+ `fp_printsrc: Prints out the value of FAC1 to the screen. You may want to call int_fac1 first to round it. Unlike BASIC's PRINT statement, this routine will not bracket the number with blanks.
+ `fp_readptr: Attempts to convert a string to a floating point value in FAC1, in a manner similar to BASIC's VAL function.
+ `fp_addoperand: Adds the operand to FAC1.
+ `fp_subtractoperand: Subtracts the operand from FAC1.
+ `fp_multiplyoperand: Multiplies the operand by FAC1.
+ `fp_divideoperand: Divides FAC1 by the operand.
+ `fp_powoperand: Raises FAC1 to the operand's power.
+ `fp_andoperand: Juggles floating point-to-integer conversions to do a bitwise AND.
+ `fp_oroperand: Likewise, but for OR.
+ jsr randomize: Calls RND(-TI) and leaves the (useless) result in FAC1. This seeds BASIC's random number generator with the number of clock ticks since poweron.
+ jsr rnd: Calls RND(1) and leaves the result in FAC1, providing a random number between 0 and 1.
+ jsr fac1_sign: Loads the SGN(FAC1) into the accumulator. This will be $01 if the accumulator is positive, $00 if it is zero, and $FF if it is negative. This routine is useful for branching based on the result of a floating point computation.
+
+
+
+ Other functions are available, but their preconditions are
+ hazier. The source file is commented with the current state of
+ knowledge.
+
+
+
+ To see some of these functions in action,
+ the examples directory includes a
+ program kinematics.oph, which reads numbers
+ in from input and computes trajectories based on them.
+
+
+
+
+
+ The Nintendo Entertainment System
+
+
+ The NES development community is somewhat more fragmented than
+ the others. A skeletal nes.oph file is
+ provided, but memory locations are not as consistently
+ named. Much sample code doesn't provide aliases for control
+ registers at all.
+
+
+
+ Conveniently creating runnable NES programs is somewhat
+ involved. Any given product was generally burned onto several
+ chips that were affixed to one of a large number of circuit
+ boards. These are often referred to as "mappers" by
+ developers because their effect is to implement various
+ bankswitching schemes. The result is a program built out of
+ parts, each with its own origin. A "Hello World"
+ sample program ships with Ophis. It does not use a bankswitcher,
+ but it does split its contents into a program chip and a
+ graphics chip, with one of two wrapper files to knit them
+ together into a file that other software will recognize. Samples
+ are given for the common iNES format and the defunct UNIF
+ format.
+
+
+
+
+ The Atari 2600 VCS
+
+
+ Of all the 8-bit development communities, the Atari developers
+ seem to be the most cohesive. The development documents
+ available are universal, and analysts and developers alike all
+ use the register names in the Stella Developer's
+ Guide. Ophis follows their lead, providing these
+ names in the header stella.oph.
+
+
+
+ The stella.oph header also replicates two
+ macros that appear in the header files distributed to budding
+ VCS developers. They are documented in the file.
+
+
+