Update manual for 2.1.

This commit is contained in:
Michael Martin 2014-05-24 05:36:17 -07:00
parent 12f0dc05d4
commit afe510735e
11 changed files with 298 additions and 114 deletions

View File

@ -403,6 +403,39 @@
are seperated by comments.
</para>
</listitem>
<listitem>
<para>
<literal>.cbmfloat</literal> <emphasis>string</emphasis>
[ , <emphasis>string</emphasis>, ... ]: 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.
</para>
<para>
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:
</para>
<programlisting>
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
</programlisting>
<para>This program will print out
a <literal>.byte</literal> directive for you to include in
your program to represent that number.</para>
</listitem>
<listitem>
<para>
<literal>.checkpc</literal> <emphasis>address</emphasis>:

Binary file not shown.

View File

@ -6,6 +6,7 @@
<!ENTITY part5 SYSTEM "tutor5.sgm">
<!ENTITY part6 SYSTEM "tutor6.sgm">
<!ENTITY part7 SYSTEM "tutor7.sgm">
<!ENTITY part8 SYSTEM "tutor8.sgm">
<!ENTITY samplecode SYSTEM "samplecode.sgm">
<!ENTITY pre1 SYSTEM "preface.sgm">
<!ENTITY cmdref SYSTEM "cmdref.sgm">
@ -42,6 +43,7 @@
&part5;
&part6;
&part7;
&part8;
</part>
<part label="II">
<title>To HLL and Back</title>

View File

@ -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.
</para>
<para>
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.
</para>
<para>
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.
</para>
<para>
This is an updated edition of <emphasis>Programming With
Ophis</emphasis>, including documentation for all new features
@ -114,7 +120,10 @@
<section>
<title>About the examples</title>
<para>
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.
</para>
<para>
The code in this book is available in

View File

@ -606,71 +606,6 @@ _done: rts
.checkpc $A000
.data
.checkpc $D000
</programlisting>
</section>
<section id="c64-2-src">
<title id="c64-2-fname"><filename>c64_0.oph</filename></title>
<programlisting>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; 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
</programlisting>
</section>
<section id="tutor7-src">

View File

@ -296,8 +296,11 @@ hello: .byte "HELLO, WORLD!", 0
</thead>
<tbody>
<row><entry><option>-o FILE</option></entry><entry>Overrides the default filename for output.</entry></row>
<row><entry><option>-l FILE</option></entry><entry>Specifies an optional listing file that gives the emitted binary in human-readable form, with disassembly.</entry></row>
<row><entry><option>-m FILE</option></entry><entry>Specifies an optional map file that gives the in-source names for every label used in the program.</entry></row>
<row><entry><option>-u</option></entry><entry>Allows the 6510 undocumented opcodes as listed in the VICE documentation.</entry></row>
<row><entry><option>-c</option></entry><entry>Allows opcodes and addressing modes added by the 65C02.</entry></row>
<row><entry><option>-4</option></entry><entry>Allows opcodes and addressing modes added by the 4502. (Experimental.)</entry></row>
<row><entry><option>-q</option></entry><entry>Quiet operation. Only reports warnings and errors.</entry></row>
<row><entry><option>-v</option></entry><entry>Verbose operation. Reports files as they are loaded.</entry></row>
</tbody>
@ -315,14 +318,16 @@ Loading hello1.oph
Assembly complete: 45 bytes output (14 code, 29 data, 2 filler)
</screen>
<para>
This will produce a file named <filename>hello.prg</filename>. If
your emulator can run <filename>PRG</filename> files directly,
this file will now run (and print <computeroutput>HELLO,
WORLD!</computeroutput>) as many times as you
type <userinput>RUN</userinput>. Otherwise, use
a <filename>D64</filename> management utility to put
the <filename>PRG</filename> on a <filename>D64</filename>, then
load and run the file off that.
This will produce a file
named <filename>hello.prg</filename>. If your emulator can
run <filename>PRG</filename> files directly, this file will now
run (and print <computeroutput>HELLO, WORLD!</computeroutput>)
as many times as you type <userinput>RUN</userinput>.
Otherwise, use a <filename>D64</filename> management utility to
put the <filename>PRG</filename> on a <filename>D64</filename>,
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.
</para>
</section>
</chapter>

View File

@ -43,6 +43,13 @@ _next: .word 0 ; End of program
.advance 2064
</programlisting>
<para>
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.
</para>
</section>
<section>
<title>Anonymous labels</title>

View File

@ -100,7 +100,9 @@
<para>
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.)
</para>
<para>

View File

@ -79,7 +79,10 @@ _done: rts
<para>
Note that we only have to name <literal>cache</literal> once, but
can use addition to refer to any offset from it.
can use addition to refer to any offset from it.<footnote><para>We
could spare ourselves some trouble here and use $fb instead of
$10, which BASIC does <emphasis>not</emphasis> use, but the
example is more thorough this way.</para></footnote>
</para>
<para>

View File

@ -2,11 +2,11 @@
<title>Advanced Memory Segments</title>
<para>
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 <literal>.text</literal> and <literal>.data</literal> commands
as we produce a final set of Commodore 64 header files.
as we produce a more sophisticated set of Commodore 64 header
files.
</para>
<section>
@ -45,9 +45,9 @@
<para>
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.
</para>
@ -60,9 +60,9 @@
<programlisting>
.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
</programlisting>
<para>
The new, improved header file is <xref linkend="c64-2-src"
endterm="c64-2-fname">. This,
like <filename>c64kernal.oph</filename>, is available for use in
your own projects in the <literal>platform/</literal> directory.
</para>
<para>
Our <literal>print'str</literal> routine is then rewritten to
declare and use a zero-page variable, like so:
@ -141,24 +134,8 @@ _done: rts
</programlisting>
<para>
That concludes our tour. The final source file
is <xref linkend="tutor7-src" endterm="tutor7-fname">.
</para>
</section>
<section>
<title>Where to go from here</title>
<para>
This tutorial has touched on everything that the assembler can
do, but it's not really well organized as a
reference. <xref linkend="ref-link"> is a better place to look
up matters of syntax or consult lists of available commands.
</para>
<para>
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 <xref linkend="tutor7-src"
endterm="tutor7-fname">.
</para>
</section>
</chapter>

211
doc/tutor8.sgm Normal file
View File

@ -0,0 +1,211 @@
<chapter>
<title>Platform-Specific Techniques</title>
<para>
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.
</para>
<section>
<title>The Commodore 64 and VIC-20</title>
<para>
In a real sense, the Commodore 64 is the &quot;native&quot;
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.
</para>
<itemizedlist>
<listitem>
<para>
<literal>c64kernal.oph</literal> 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 <literal>chrout</literal> and <literal>rdtim</literal>
by name.
</para>
</listitem>
<listitem>
<para>
<literal>c64header.oph</literal> 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 <literal>c64kernal.oph</literal> may be useful, but are
not included in this header.
</para>
</listitem>
<listitem>
<para>
<literal>c64_0.oph</literal> 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&mdash;just include it at
the top of your source file and use <literal>RTS</literal>
to end your program&mdash;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.
</para>
</listitem>
<listitem>
<para>
<literal>libbasic64.oph</literal> 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 <literal>c64_0.oph</literal>, 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.
</para>
</listitem>
<listitem>
<para>
<literal>vic20.oph</literal> is a header that will work for
the <emphasis>unexpanded</emphasis> 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&mdash;the VIC-20 does not have enough RAM to
gain anything from these techniques.
</para>
</listitem>
<listitem>
<para>
<literal>vic20x.oph</literal> does the same, but for a
VIC-20 with one or more memory expansions.
</para>
</listitem>
</itemizedlist>
<section>
<title>Using LIBBASIC64</title>
<para>
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.
</para>
<para>
The <literal>libbasic64.oph</literal> library is an attempt to
address this. It is currently considered highly experimental,
but initial results are very promising.
</para>
<para>
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 <literal>.cbmfloat</literal> directive, which takes a
string and produces the requisite five-byte value.
</para>
<para>
The floating point functions in BASIC all operate on FAC1 and
are relatively reliable. The
functions <literal>abs_fac1</literal>, <literal>atn_fac1</literal>, <literal>cos_fac1</literal>, <literal>exp_fac1</literal>, <literal>int_fac1</literal>, <literal>log_fac1</literal>, <literal>rnd_fac1</literal>, <literal>sgn_fac1</literal>, <literal>sin_fac1</literal>,
and <literal>tan_fac1</literal> 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:
</para>
<itemizedlist>
<listitem><para><literal>`f_move</literal> <emphasis>dest, source</emphasis>: Copy a five-byte floating point value from <emphasis>source</emphasis> to <emphasis>dest</emphasis>.</para></listitem>
<listitem><para><literal>`fp_load</literal> <emphasis>src</emphasis>: Loads FAC1 with the floating point constant specified by <emphasis>src</emphasis>.</para></listitem>
<listitem><para><literal>`fp_store</literal> <emphasis>dest</emphasis>: Saves the value of FAC1 to the named memory location.</para></listitem>
<listitem><para><literal>`fp_print</literal> <emphasis>src</emphasis>: Prints out the value of FAC1 to the screen. You may want to call <literal>int_fac1</literal> first to round it. Unlike BASIC's <literal>PRINT</literal> statement, this routine will not bracket the number with blanks.</para></listitem>
<listitem><para><literal>`fp_read</literal> <emphasis>ptr</emphasis>: Attempts to convert a string to a floating point value in FAC1, in a manner similar to BASIC's <literal>VAL</literal> function.</para></listitem>
<listitem><para><literal>`fp_add</literal> <emphasis>operand</emphasis>: Adds the operand to FAC1.</para></listitem>
<listitem><para><literal>`fp_subtract</literal> <emphasis>operand</emphasis>: Subtracts the operand from FAC1.</para></listitem>
<listitem><para><literal>`fp_multiply</literal> <emphasis>operand</emphasis>: Multiplies the operand by FAC1.</para></listitem>
<listitem><para><literal>`fp_divide</literal> <emphasis>operand</emphasis>: Divides FAC1 by the operand.</para></listitem>
<listitem><para><literal>`fp_pow</literal> <emphasis>operand</emphasis>: Raises FAC1 to the operand's power.</para></listitem>
<listitem><para><literal>`fp_and</literal> <emphasis>operand</emphasis>: Juggles floating point-to-integer conversions to do a bitwise AND.</para></listitem>
<listitem><para><literal>`fp_or</literal> <emphasis>operand</emphasis>: Likewise, but for OR.</para></listitem>
<listitem><para><literal>jsr randomize</literal>: 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.</para></listitem>
<listitem><para><literal>jsr rnd</literal>: Calls RND(1) and leaves the result in FAC1, providing a random number between 0 and 1.</para></listitem>
<listitem><para><literal>jsr fac1_sign</literal>: 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.</para></listitem>
</itemizedlist>
<para>
Other functions are available, but their preconditions are
hazier. The source file is commented with the current state of
knowledge.
</para>
<para>
To see some of these functions in action,
the <literal>examples</literal> directory includes a
program <literal>kinematics.oph</literal>, which reads numbers
in from input and computes trajectories based on them.
</para>
</section>
</section>
<section>
<title>The Nintendo Entertainment System</title>
<para>
The NES development community is somewhat more fragmented than
the others. A skeletal <literal>nes.oph</literal> file is
provided, but memory locations are not as consistently
named. Much sample code doesn't provide aliases for control
registers at all.
</para>
<para>
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 &quot;mappers&quot; 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 &quot;Hello World&quot;
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.
</para>
</section>
<section>
<title>The Atari 2600 VCS</title>
<para>
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 <emphasis>Stella Developer's
Guide</emphasis>. Ophis follows their lead, providing these
names in the header <literal>stella.oph</literal>.
</para>
<para>
The <literal>stella.oph</literal> header also replicates two
macros that appear in the header files distributed to budding
VCS developers. They are documented in the file.
</para>
</section>
</chapter>