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. + + + .cbmfloat string + [ , 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. + .checkpc address: 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 - -
-
- <filename>c64_0.oph</filename> - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; 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_move dest, source: Copy a five-byte floating point value from source to dest. + `fp_load src: Loads FAC1 with the floating point constant specified by src. + `fp_store dest: Saves the value of FAC1 to the named memory location. + `fp_print src: 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_read ptr: Attempts to convert a string to a floating point value in FAC1, in a manner similar to BASIC's VAL function. + `fp_add operand: Adds the operand to FAC1. + `fp_subtract operand: Subtracts the operand from FAC1. + `fp_multiply operand: Multiplies the operand by FAC1. + `fp_divide operand: Divides FAC1 by the operand. + `fp_pow operand: Raises FAC1 to the operand's power. + `fp_and operand: Juggles floating point-to-integer conversions to do a bitwise AND. + `fp_or operand: 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. + +
+