Update manual for 2.1.
This commit is contained in:
parent
12f0dc05d4
commit
afe510735e
|
@ -403,6 +403,39 @@
|
||||||
are seperated by comments.
|
are seperated by comments.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</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>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
<literal>.checkpc</literal> <emphasis>address</emphasis>:
|
<literal>.checkpc</literal> <emphasis>address</emphasis>:
|
||||||
|
|
Binary file not shown.
|
@ -6,6 +6,7 @@
|
||||||
<!ENTITY part5 SYSTEM "tutor5.sgm">
|
<!ENTITY part5 SYSTEM "tutor5.sgm">
|
||||||
<!ENTITY part6 SYSTEM "tutor6.sgm">
|
<!ENTITY part6 SYSTEM "tutor6.sgm">
|
||||||
<!ENTITY part7 SYSTEM "tutor7.sgm">
|
<!ENTITY part7 SYSTEM "tutor7.sgm">
|
||||||
|
<!ENTITY part8 SYSTEM "tutor8.sgm">
|
||||||
<!ENTITY samplecode SYSTEM "samplecode.sgm">
|
<!ENTITY samplecode SYSTEM "samplecode.sgm">
|
||||||
<!ENTITY pre1 SYSTEM "preface.sgm">
|
<!ENTITY pre1 SYSTEM "preface.sgm">
|
||||||
<!ENTITY cmdref SYSTEM "cmdref.sgm">
|
<!ENTITY cmdref SYSTEM "cmdref.sgm">
|
||||||
|
@ -42,6 +43,7 @@
|
||||||
&part5;
|
&part5;
|
||||||
&part6;
|
&part6;
|
||||||
&part7;
|
&part7;
|
||||||
|
&part8;
|
||||||
</part>
|
</part>
|
||||||
<part label="II">
|
<part label="II">
|
||||||
<title>To HLL and Back</title>
|
<title>To HLL and Back</title>
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
chip used in the vast majority of the classic 8-bit computers and
|
chip used in the vast majority of the classic 8-bit computers and
|
||||||
consoles. Its primary design goals are code readability and output
|
consoles. Its primary design goals are code readability and output
|
||||||
flexibility - Ophis has successfully been used to create programs
|
flexibility - Ophis has successfully been used to create programs
|
||||||
for the Nintendo Entertainment System, the Atari 2600, and the
|
for the Nintendo Entertainment System, the Atari 2600, and various
|
||||||
Commodore 64.
|
8-bit Commodore machines.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Ophis's syntax is noticably different from the formats
|
Ophis's syntax is noticably different from the formats
|
||||||
|
@ -66,6 +66,12 @@
|
||||||
and to become better able to interoperate with other
|
and to become better able to interoperate with other
|
||||||
toolchains. It was this process that led to Ophis 2.
|
toolchains. It was this process that led to Ophis 2.
|
||||||
</para>
|
</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>
|
<para>
|
||||||
This is an updated edition of <emphasis>Programming With
|
This is an updated edition of <emphasis>Programming With
|
||||||
Ophis</emphasis>, including documentation for all new features
|
Ophis</emphasis>, including documentation for all new features
|
||||||
|
@ -114,7 +120,10 @@
|
||||||
<section>
|
<section>
|
||||||
<title>About the examples</title>
|
<title>About the examples</title>
|
||||||
<para>
|
<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>
|
||||||
<para>
|
<para>
|
||||||
The code in this book is available in
|
The code in this book is available in
|
||||||
|
|
|
@ -606,71 +606,6 @@ _done: rts
|
||||||
.checkpc $A000
|
.checkpc $A000
|
||||||
.data
|
.data
|
||||||
.checkpc $D000
|
.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>
|
</programlisting>
|
||||||
</section>
|
</section>
|
||||||
<section id="tutor7-src">
|
<section id="tutor7-src">
|
||||||
|
|
|
@ -296,8 +296,11 @@ hello: .byte "HELLO, WORLD!", 0
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<row><entry><option>-o FILE</option></entry><entry>Overrides the default filename for output.</entry></row>
|
<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>-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>-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>-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>
|
<row><entry><option>-v</option></entry><entry>Verbose operation. Reports files as they are loaded.</entry></row>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -315,14 +318,16 @@ Loading hello1.oph
|
||||||
Assembly complete: 45 bytes output (14 code, 29 data, 2 filler)
|
Assembly complete: 45 bytes output (14 code, 29 data, 2 filler)
|
||||||
</screen>
|
</screen>
|
||||||
<para>
|
<para>
|
||||||
This will produce a file named <filename>hello.prg</filename>. If
|
This will produce a file
|
||||||
your emulator can run <filename>PRG</filename> files directly,
|
named <filename>hello.prg</filename>. If your emulator can
|
||||||
this file will now run (and print <computeroutput>HELLO,
|
run <filename>PRG</filename> files directly, this file will now
|
||||||
WORLD!</computeroutput>) as many times as you
|
run (and print <computeroutput>HELLO, WORLD!</computeroutput>)
|
||||||
type <userinput>RUN</userinput>. Otherwise, use
|
as many times as you type <userinput>RUN</userinput>.
|
||||||
a <filename>D64</filename> management utility to put
|
Otherwise, use a <filename>D64</filename> management utility to
|
||||||
the <filename>PRG</filename> on a <filename>D64</filename>, then
|
put the <filename>PRG</filename> on a <filename>D64</filename>,
|
||||||
load and run the file off that.
|
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>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
|
@ -43,6 +43,13 @@ _next: .word 0 ; End of program
|
||||||
.advance 2064
|
.advance 2064
|
||||||
</programlisting>
|
</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>
|
||||||
<section>
|
<section>
|
||||||
<title>Anonymous labels</title>
|
<title>Anonymous labels</title>
|
||||||
|
|
|
@ -100,7 +100,9 @@
|
||||||
<para>
|
<para>
|
||||||
No global or anonymous labels may be defined inside a macro:
|
No global or anonymous labels may be defined inside a macro:
|
||||||
temporary labels only persist in the macro expansion itself.
|
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>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
|
|
@ -79,7 +79,10 @@ _done: rts
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Note that we only have to name <literal>cache</literal> once, but
|
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>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
<title>Advanced Memory Segments</title>
|
<title>Advanced Memory Segments</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
This is the last section of the Ophis tutorial. By now we've
|
By now we've covered the basics of every command in the assembler;
|
||||||
covered the basics of every command in the assembler; in this
|
in this final installment we show the full capabilities of
|
||||||
final installment we show the full capabilities of
|
|
||||||
the <literal>.text</literal> and <literal>.data</literal> commands
|
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>
|
</para>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
|
@ -45,9 +45,9 @@
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Now, actually, the rest of the zero page is reserved too:
|
Now, actually, the rest of the zero page is reserved too:
|
||||||
locations $02-$7F are used by the BASIC interpreter, and
|
locations $02-$8F are used by the BASIC interpreter, and
|
||||||
locations $80-$FF are used by the KERNAL. We don't need the
|
locations $90-$FF are used by the KERNAL. We don't need the
|
||||||
BASIC interpreter, though, so we can back up all of $02-$7F at
|
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.
|
the start of our program and restore it all when we're done.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
@ -60,9 +60,9 @@
|
||||||
<programlisting>
|
<programlisting>
|
||||||
.scope
|
.scope
|
||||||
; Cache BASIC zero page at top of available RAM
|
; Cache BASIC zero page at top of available RAM
|
||||||
ldx #$7E
|
ldx #$8e
|
||||||
* lda $01, x
|
* lda $01, x
|
||||||
sta $CF81, x
|
sta $cf81, x
|
||||||
dex
|
dex
|
||||||
bne -
|
bne -
|
||||||
|
|
||||||
|
@ -81,8 +81,8 @@
|
||||||
sta $01
|
sta $01
|
||||||
|
|
||||||
; Restore BASIC zero page
|
; Restore BASIC zero page
|
||||||
ldx #$7E
|
ldx #$8e
|
||||||
* lda $CF81, x
|
* lda $cf81, x
|
||||||
sta $01, x
|
sta $01, x
|
||||||
dex
|
dex
|
||||||
bne -
|
bne -
|
||||||
|
@ -96,13 +96,6 @@ _main:
|
||||||
.scend
|
.scend
|
||||||
</programlisting>
|
</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>
|
<para>
|
||||||
Our <literal>print'str</literal> routine is then rewritten to
|
Our <literal>print'str</literal> routine is then rewritten to
|
||||||
declare and use a zero-page variable, like so:
|
declare and use a zero-page variable, like so:
|
||||||
|
@ -141,24 +134,8 @@ _done: rts
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
That concludes our tour. The final source file
|
The final source file is <xref linkend="tutor7-src"
|
||||||
is <xref linkend="tutor7-src" endterm="tutor7-fname">.
|
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.
|
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
|
@ -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 "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.
|
||||||
|
</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—just include it at
|
||||||
|
the top of your source file and use <literal>RTS</literal>
|
||||||
|
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.
|
||||||
|
</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—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 "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.
|
||||||
|
</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>
|
Loading…
Reference in New Issue