Showing posts with label Replica 1. Show all posts
Showing posts with label Replica 1. Show all posts

Wednesday, June 11, 2014

Abandoned Farmhouse Adventure now in Google Play Store

Back in April 2012, I wrote a text adventure game  as an experiment to try out the CC65 C compiler on the Briel Replica 1 computer  (an Apple 1 replica). Because it was written in C, it also ran under Linux, and any platform that supported a reasonable C compiler. I also ported it  to the Briel Altair 8800 computer running CP/M using the BDS C compiler.

When the Raspberry Pi store opened, I packaged it and submitted it as one of the first applications in the Raspberry Pi store.

Later, I made a GUI version using the Qt Toolkit , which is portable to a number of platforms. I intend to release the Qt version into the Raspberry Pi store, but have not gotten around to doing that yet.

With Qt now supporting Android, I tried building it for Android to run on a tablet, and it worked almost flawlessly without any changes. I made a few small tweaks for Android, and packaged it for the Google Play store. It is now available as a free Android application.

Android Version of The Abandoned Farmhouse Adventure
I doubt that any application before has run on an Apple 1, CP/M, Linux desktop, Raspberry Pi, and Android tablet - devices that span almost 40 years of computing and differences in computing power of several thousand times.

Wednesday, May 21, 2014

Updates: Apple II Monitor Port and GR-64 Video

A couple of updates to recent blog posts: I did a little more work on the Apple II Monitor port to the Apple 1, getting the source code to assemble the version that includes the Woz Monitor at the end. This version can be burned to a ROM (or EPROM or EEPROM) in the Replica 1, so you can have both the original Woz Monitor and Apple II Monitor in ROM from powerup. I confirmed that it does work when programmed into a ROM. It also works in the POM1 Apple 1 Emulator. As before, the Apple II Monitor port can be found here.

Monday, January 14, 2013

More About the Abandoned Farmhouse Adventure


I mentioned here earlier that I ported my Abandoned Farmhouse Adventure  game to the Raspberry Pi and got it into the Pi Store as a free download. Here are some more details about the game and how it was developed for people that may be interested.

The program was written in the C programming language, consisting of just over 800 lines of source code. I originally wrote it in March 2012 as a game for the Replica 1 Computer, a replica of the first computer, the Apple 1, offered by Apple Computer in 1976.

The Briel Replica 1 Computer
On the Replica 1 it was compiled using the CC65 compiler which supports the 8-bit 6502 microprocessor used by the Replica 1 (and Apple 1). It took me a few evenings and weekend mornings to design and write the game. The game had to fit within the hardware constraints of the Replica 1: a one MHz 8-bit processor with only a few kilobytes of memory and only text output.

I did most testing of the game on a Linux desktop system using the GNU gcc compiler, as it was faster and easier to build and debug than on the Replica 1.

The game was announced on the Briel Computers forum and made available to any Replica 1 or Apple 1 computer users who wanted to try it.

I've been following the Raspberry Pi since it's early development. With the announcement of the Raspberry Pi store, I thought it would be fun to get an application in the new store. The adventure game was already running on Linux so getting it on the Linux-based Raspberry Pi should be straightforward. Porting it to the Raspberry Pi involved adding lower case text (the Apple 1 could only display upper case text). I also removed some code that was specific to the CC65 compiler. Most of the work was figuring out how to publish an application in the Raspberry Pi app store, and waiting for it to pass through the application approval process.

Screen Shot Of The Game
For people trying the game, I won't give a solution or any spoilers, but here are a few hints. I suggest drawing out a map on a piece of paper and making notes as you play the game. Pay attention to any messages, like needing food or water, as these will soon become important in the game. Not all items in the game are necessarily needed to solve it; some may be red herrings. The game will take some time to solve. Keep at it. If you get frustrated, set it aside for a while and you may think of some new insight into how to solve it.

I would really like to hear from you if you solved the game, or even if you played it but did not complete it yet. As I write this the game has had 361 downloads but no one has actually reported completing the game. I don't think I made it too hard, but it is difficult as the developer to stand back and assess how challenging the game is.

I have been planning to make a version of the games with a Qt-based graphical user interface on it, which would be less like a retro text adventure game but more playable by people accustomed to modern GUIs.

Early Prototype of GUI Version of the Game
The game is open source and published under an Apache license. The source code can be found here. You are free to share, port, or modify the game subject to the terms of the Apache license. If you are really stuck solving the game and are at all fluent in C code, you could look at the source code to get some hints. Much of the code is data-driven and could be used to implement an entirely different adventure just by changing the map, strings, and some of the logic that handles special actions.

Finally, the farm described here is based on a real farmhouse where my father lived many years ago, right down to the layout of most of the rooms. And I also have a grandson who was almost three years old at the time I wrote this. It is interesting to think that in a few years he may come across this game in which he appears and maybe play it.

Saturday, October 6, 2012

The Apple 1 Cassette Interface


The Apple Cassette Interface (ACI) was the only accessory sold for the Apple 1 computer. It allowed saving and loading programs from cassette tape using an inexpensive tape recorder.

Vince Briel  recently made a batch of replica ACI boards both as kits or pre-assembled. The board is similar to the original except using a more easily obtainable EEPROM chip rather than the ROM chips on the original design. I got one of the first batch of kits and assembled it.

ACI parts and manual ready to be assembled
I have a couple of tape recorders from that era. I have a GE model that I bought around 1980 and used with my Ohio Scientific Superboard computer for tape storage. I also recently picked up a Panasonic model from the 1970s or 1980s at a thrift store.  I don't the Panasonic RQ-2102 model that Apple originally recommended (amazingly it is still be manufactured and available).

GE Cassette Recorder circa 1980
Panasonic Recorder picked up a thrift shop
Panasonic RQ-2102 Recommended by Apple
The original Apple Cassette Interface manual is available on-line. The software is on-board the ACI and consists of only 256 bytes of code written by Woz. It is primitive and has no error detection. The later Apple II had a similar cassette interface circuit built into the motherboard (in models up to the Apple 2c). The Apple II used a similar storage scheme but added a checksum verification to detect errors.

Assembled ACI Replica
I haven't got mine to work reliably yet. I am working with some other kit builders to track down why. It is known to be tricky to get working. As well as a tape recorder I've been using my computer's sound card and an oscilloscope to debug it. I'll report more here on my progress toward getting it to work reliably. 

ACI Installed in the Replica 1

Sunday, August 12, 2012

Replica 1 Quick Reference, Apple 1 on the Raspberry Pi, and the return of IMSAI


Earlier I made a one page reference of useful addresses for the Replica 1. I've extended that into a more comprehensive four page quick reference. You can download it from hereThat directory also has some documents I wrote like a summary of the 65C02 and 65816 processors and some errata for Apple 1 manuals.




I recently got a Raspberry Pi board. This is a very small (credit card sized), low cost ($35) embedded desktop computer that can run Linux. For fun I compiled the POM1 Apple 1 Emulator on it. It ran quite well although it was a little slow on the Raspberry Pi's 600MHz ARM CPU. I've ordered a hardware expansion board for the Raspberry Pi called the Gertboard and plan to use if for some hardware experiments.




I've started playing with the Propeller CPU on the Replica 1. It is quite an amazing chip - 8 CPUs with shared memory, a built-in high level language interpreter as well as machine language, and hardware I/O ports. It can even generate video (which it does for the Replica 1). I'll have more to say here as I explore it further.




I'm looking forward to getting the Apple Cassette Interface when Briel computers starts shipping them. It sounds like big things are in store for Briel Computers. Vince Briel is planning to purchase the assets
of IMSAI computer. They were one of the first home computer manufacturers (along with Altair) and a portion of the company was still in business. He is hoping to restart a project they had to introduce a new replica of the original IMSAI 8080 computer.

Wednesday, August 8, 2012

Converting Between Floating Point and Human Readable Format


In my last post I mentioned 6502 code that can convert between ASCII and floating point formats that was written by Marvin L De Jong and published in the February and April 1981 issues of COMPUTE! magazine.

I've now entered it and ported it to the CC65 assembler to run on the Replica 1.

As often seems to be the case, there were a number of errors in the printed code, such as symbols that were never defined. The "#" sign was also not used to specify immediate addressing (this was apparently a coding convention that the author followed in all of his published code).

Fortunately it seemed that the generated machine code in the listing was correct, so in most cases I was able to use that as a reference to determine what the code should be.

I also had to combine the code in the first article with changes in the second one as there was no complete listing of the final software.

The code used some i/o routines for the AIM-65 machine so those needed to be be replaced with equivalents for the Replica 1.

After a couple of evenings of porting and testing I had the string to floating point and floating point to string functions working (De Jong refers to it as "BCD format" but it is really an ASCII string format). So, for example, I could now convert a string like "+6.02214E23" or "-1.2E-19" to floating point and back to ASCII. I then updated my little test/demo program to support calling the new routines.

The floating point format used by the De Jong code is a little different from the format used by the Woz code, but I was able to convert them easily enough.

The final result is the demo program which exercises all the functions. Here is an example run:

FLOATING POINT DEMONSTRATION PROGRAM

F - FIXED TO FLOATING POINT
P - FLOATING TO FIXED POINT
L - NATURAL LOG
N - COMMON LOG
E - EXPONENTIAL
A - FLOATING POINT ADD
S - FLOATING POINT SUBTRACT
M - FLOATING POINT MULTIPLY
D - FLOATING POINT DIVIDE
B - STRING TO FLOATING POINT
T - FLOATING POINT TO STRING
? - THIS HELP SCREEN
X - EXIT

SELECT A FUNCTION: B
STRING TO FLOATING POINT
ENTER FP STRING: 1234
FLOATING POINT IS: 8A 4D2000

SELECT A FUNCTION: T
FLOATING POINT TO STRING
ENTER EXPONENT AND MANTISSA: 8A 4D2000
FLOATING POINT IS: 1234

SELECT A FUNCTION: B
STRING TO FLOATING POINT
ENTER FP STRING: 6.02214E23
FLOATING POINT IS: CE 7F8616

SELECT A FUNCTION: T
FLOATING POINT TO STRING
ENTER EXPONENT AND MANTISSA: CE 7F8616
FLOATING POINT IS: 60221399.E16

With the facilities here you could implement a math program like a scientific calculator. I may do that at some point.

I learned a little about floating point code with this project. It also reminded me that back at the time this code was written there was no standard for representing floating point numbers. That was addressed by the IEEE Standard for Floating-Point Arithmetic (IEEE 754) and most modern CPU chips that have floating point hardware now support this standard, and language compilers typically support it in their run-time libraries. CPUs that lack floating point hardware typically emulate it in software, using code much like the 6502 code here, but more complex and typically written in C.

As usual, all of the code can be found here and you are welcome to use it.

Wednesday, August 1, 2012

Musing on Kit Building


I love building electronic kits, and there is a long tradition of kit building among people who tinker with electronics, including amateur radio operators, that goes back almost 100 years.

That tradition continues today with products like the replica computers offered by Briel Computers and amateur radio kits from companies like Elecraft.

Despite predictions that surface mount technology and the reduced emphasis on electricity and electronics in education would mean the demise of kits, the popularity of kit building has grown in the last ten years or so, as part of what is now often called the "maker" movement.

While kits have differing levels of complexity in terms of the number of parts involved and effort to assemble them, it seems to me that there are four fundamentally different levels of kit building.

Let me expound my theory, which I think is original if not particularly insightful.

Level 1: Assembling From Pre-built Components or Modules.

Kits at this level involve assembling pre-built components and mechanically connecting pieces together but doesn't involve any soldering, or if it does, just simple soldering of wires and connectors.

I've heard people talk about "building their own computer" and more often than not they mean building one at this level -- taking a commercial motherboard, case, and power supply, and connecting them together into a working computer.

Examples of this category include the pre-assembled Apple Replica 1, the Arduino embedded controller or the Elecraft K3 amateur radio transceiver.

An Arduino Embedded Controller

This can be a good way to get started in electronics and build up confidence before you are ready to pick up a soldering iron.

Level 2: Building a Commercial Kit 

The next level involves assembly of a kit that requires soldering as well as mechanical assembly. You need to be able to solder competently and identify electronic components. You don't need to understand the circuit being built and don't need expensive test equipment although a Digital Multi Meter (DMM) is very useful.

The kit may include a professional case, power supply, etc. or may leave it up to the user to provide these.

The Heathkit company was the premiere source of kits of this type for many years and was renowned for the quality of its manuals and the professional look of the kits when assembled.

Briel Computers and many other companies offer similar kits of this type.

An Assortment of Heathkit Equipment

Level 3: Building From a Provided Design

The next step up is to take an electronic design, such as one described in a magazine or book article, or possibly as little as a schematic diagram, and realizing it as working device.

This involves finding and sourcing all the components, figuring out how to lay out the parts and deciding what construction technique to use (such as simple point to point wiring, a printed circuit board, or others such as "ugly" construction style).

This level offers more risks and challenges. There may be hidden gotchas in the design that will depend on the parts used or how it is assembled. There make even be errors in the design.

The builder needs to understand the circuit although not how all component values were determined. You may need more extensive test equipment such as an oscilloscope, signal generators, etc. in order to test and debug it. You may need tune or calibrate the circuit for proper operation.

This was how a lot of equipment was built by radio amateurs in the old days and still today. Circuits were often published in books like the Radio Amateur's Handbook or periodicals like QST magazine.

It is very rewarding as the end result is unique and there are often opportunities for making modifications.

An example from amateur radio is a transceiver (transmitter and receiver) called the the Ugly Weekender that was published in the amateur radio magazine QST in the 1980s. I built this unit using "ugly" construction on a bare copper board and built it into a case.
My Version of The Ugly Weekender

Level 4: Building Your Own Design

This is the ultimate level where you are no longer building a kit, but your own design.

You design the circuit yourself (possibly based on some existing design) and assemble it. To be successful you need to fully understand the circuit. You may even want to simulate the design using circuit simulation tools, or at least prototype key portions of it to verify the design.

This level of project can take months or more depending on the complexity and the time available to spend on it. It is the most risky but also the most rewarding if successful. If you succeed at this you've reached the "black belt" level.

A small example could be the RAM/EEPROM card I designed and built for the Apple Replica 1.
Replica 1 RAM/EEPROM Card

In summary, kit building can be categorized into the four levels I outlined. In practice there is often a grey area between the levels.

So the next time you work on a kit or electronic project, maybe you will ponder at what level you are and maybe consider moving your kit building prowess up to the next level.

Tuesday, July 31, 2012

A YUMmy New Game


I wanted to write another game for the Replica 1, and after considering a few alternatives, I decided to write a computer version of YUM, a game that is popular with our family.


YUM is a dice game, similar to games known as Yahtzee, Yacht and Generala. Each player rolls five dice up to three times and then applies the dice toward a category to claim points. The game has 12 rounds during which each player attempts to claim the most points in each category.

The winner is the person scoring the most points at the end of the game. This version supports up to three players of which any can be human or computer players.

It would be a little frustrating to write in BASIC and tedious in assembler so I wrote it in C using the CC65 6502 compiler/assembler. This had the advantage that I could develop and test it on a desktop Linux system.



There is nothing particularly novel about the code. The computer players play a relatively good game based on some simple rules. The game could support more than three players by changing a compile-time constant -- the only limitation is that the screen size only conveniently fits a table of scores for three players.



Because it was intended to run on the Replica 1 it was kept small and efficient to run within the 32K memory limit and only use uppercase characters and fit on a 40x24 character screen.





The source is released under an Apache license. Both the source code and a binary that will run on a Replica 1system  can be found at here.

If you want to run it on a real Apple 1 or similar, you will need to have just over 16K of RAM. With a little effort I could probably get the code size down a little to fit in 16K (the Replica 1 has 32K).





For my next Replica 1 project I am eagerly awaiting the Apple Cassette Interface kits that Vince Briel is offering. I expect to be one of the first beta testers for this, and I have a cassette tape player ready to go.


Saturday, July 21, 2012

Getting Info About the System


I recently added a few more features to JMON. The main one is a new iNfo command which displays information about the system it is running on. Here is sample output:

         CPU TYPE: 65C02
        CPU SPEED: 2.0 MHZ
RAM DETECTED FROM: $0000 TO $7FFF
       NMI VECTOR: $0F00
     RESET VECTOR: $FF00
   IRQ/BRK VECTOR: $0100
         ACI CARD: NOT PRESENT
       CFFA1 CARD: NOT PRESENT
   MULTI I/O CARD: PRESENT
        BASIC ROM: PRESENT
     KRUSADER ROM: PRESENT
       WOZMON ROM: PRESENT

The way some of this information was generated is somewhat interesting. I'll explain a bit about how the code was implemented.

To determine the CPU type I used some code from the Western Design Center manual for the 65xx series processors. The code first distinguishes between 6502 and 65C02 processors by the behavior of the negative flag in decimal mode. The 65C02 fixed the behavior to make the flag valid (also V and C) while the 6502 did not. It then tries a 65816 instruction which will change the carry flag but is an unimplemented instruction and hence a NOP on the 65C02. From this it determines if it is running on a 6502, 65C02, or 65816 processor.

There are different manufacturers of 65C02. I don't know of any easy way to distinguish between a Rockwell and WDC 65C02. Thw only added instructions on the WDC are STP and WAI which both stop the CPU from running. They require either a reset or an interrupt to restart the CPU.

To find the range of RAM the code does the following. Starting from address zero, it in turn writes all ones, all zeroes, and alternating ones and zeroes to each memory location. If the same data is read back, it is considered RAM. The original data at the location is then written back to avoid corrupting what is in memory (namely, JMON). This is done until memory is found that cannot be written to and read back with the same data. I then stop, so the test only checks for contiguous RAM starting at zero.

A wrinkle is to avoid writing to the area of memory where the code itself is running since it would get corrupted in the middle of execution. I do this by avoiding testing the 256 byte page where the memory test code resides.

Next is the CPU speed. We want to determine the approximate clock speed of the CPU. But how, since we have no reference to actual time? The trick I used is to make use of a serial port, which is available when a Multi I/O board is present. If we send some characters out the serial port and see how many CPU cycles it takes, we can determine how fast the CPU is running since the serial port works at baud rates that are independent of the CPU clock speed. The code is calculated to give a value that is approximately the clock speed in megahertz to two significant figures.

For testing if certain ROMS are present, like the Krusader assembler, we can check the first few bytes for known data.

For expansion cards, like the CFFA1, they may have ID bytes in hardware (the CFFA1 does) or we can look at the hardware registers like the 6551 on the Multi I/O board and check for behavior of the registers, such as specific bits that can or can't be changed. I wrote tests for the cards that I have, the CFFA1 flash card, Multi I/O card, and ACI Apple Cassette Interface (the latter I don't yet have).

I tested the new info command with 6502, 65C02, and 65816 processors and 1 MHz and 2 MHz crystal oscillators. I also tested it on the POM1 emulator. A screenshot under POM1 is shown below.

Info Command Running on the POM1 Emulator

With these changes I am running out of features to add to JMON so I am considering it to be feature complete and calling it version 1.0.

I noticed it recently exceeded 8K in size, so it no longer fits in a single 8K EPROM. I could reduce it to under 8K by disabling some features. The disassembler has some reasonably large tables (which the assembler also uses).

Saturday, July 14, 2012

JMON Trace Function


I've implemented one of the features missing from JMON, and one that I had been relying on Krusader's mini monitor for: an instruction trace function. This function allows you to single step through a program, see a disassembly of the current instruction, and see the values of the hardware registers. This feature is almost indispensable for debugging code. Krusader does this but I wanted to write my own.

I can think of at least three ways to single step code. One is a hardware solution. The Apple 1 manual actually shows a circuit that does this, and presumably Woz used this circuit to debug the Apple 1. This approach is very useful for bringing up new hardware that may not yet be working, but it is complex and expensive.

A second approach is the use the breakpoint instruction (BRK). By inserting a BRK instruction in code, when executed it can jump to the break vector which can run code which shows the current values of the registers. You can then replace the BRK with the original instruction and place a BRK at the next instruction, and continue execution. A disadvantage of this approach is that it only works for code in RAM and not ROM, since the program memory must be written to with the BRK instruction.

A third approach, and the one I used, is to look at the next instruction to be executed, copy it to a buffer, and execute it in place. The instruction can be followed by code that jumps back into the trace code in the monitor program. This approach has the advantage of working even for code that is in ROM.

To make this work there are a couple of wrinkles. Some instructions change the flow of control (e.g. JMP and JSR) and would jump out of the trace code. To trace these I simulate instead of execute them, doing the equivalent of what the instruction would do. For example. a JMP instruction just needs to update the value of the program counter. These special instructions are JMP, JSR, RTS, RTI, and BRK. Similar are the branch instructions. Initially I thought I would simulate these, looking at the CPU registers to determine whether the branch was taken or not. This would get a little complex as there are about 8 branch instructions to simulate, each checking a different condition. Instead I use a simpler approach that can use the same code for all branches. I execute the branch instruction in the buffer, but I adjust the branch destination so it jumps to a known location in the trace code. Whether the branch is taken or not, it stays under control of the trace code.

My trace function produces similar output to Krusader's mini monitor. You can set the register values use the Register command, including the Program Counter. The "." command traces/executes one instruction.

The breakpoint feature of JMON works in conjunction with this. If a breakpoint is hit, it updates the register values and you can single step as desired. You can also use the Go command to execute from the current program counter address.

It took a little work to get all of this correct for all instructions. It leveraged the previous work on the disassembler and mini assembler. For example, I needed to know the length of each instruction and this information was already available in tables used by the disassembler.

A sample session is shown below. Commands entered by the user are in bold. The actual trace commands "." are not echoed.

JMON MONITOR 0.99 BY JEFF TRANTER
? R
A-00 X-00 Y-00 S-0140 P-00 ........
0000   00          BRK
A-00 X-00 Y-00 S-0140 P-00 ........
PC-6000
? R
A-00 X-00 Y-B0 S-0140 P-00 ........
6000   EA          NOP
A-Esc
? A-00 X-00 Y-B0 S-0140 P-30 ..-B....
6001   A9 01       LDA   #$01
? A-01 X-00 Y-B0 S-0140 P-30 ..-B....
6003   A0 01       LDY   #$01
? A-01 X-00 Y-01 S-0140 P-30 ..-B....
6005   A2 01       LDX   #$01
? A-01 X-01 Y-01 S-0140 P-30 ..-B....
6007   08          PHP
? A-01 X-01 Y-01 S-013F P-30 ..-B....
6008   68          PLA
? A-30 X-01 Y-01 S-0140 P-30 ..-B....
6009   38          SEC
? A-30 X-01 Y-01 S-0140 P-31 ..-B...C
600A   18          CLC
? A-30 X-01 Y-01 S-0140 P-30 ..-B....
600B   69 01       ADC   #$01
? A-31 X-01 Y-01 S-0140 P-30 ..-B....
600D   F8          SED
? A-31 X-01 Y-01 S-0140 P-38 ..-BD...
600E   69 10       ADC   #$10
? A-41 X-01 Y-01 S-0140 P-38 ..-BD...
6010   D8          CLD
? A-41 X-01 Y-01 S-0140 P-30 ..-B....
6011   4C 17 60    JMP   $6017
? A-41 X-01 Y-01 S-0140 P-30 ..-B....
6017   20 15 60    JSR   $6015
? A-41 X-01 Y-01 S-013E P-30 ..-B....
6015   EA          NOP
? A-41 X-01 Y-01 S-013E P-30 ..-B....
6016   60          RTS
? A-41 X-01 Y-01 S-0140 P-30 ..-B....
601A   A9 28       LDA   #$28


As part of my testing I modified the code to stay in trace mode and ran the Woz monitor and Apple BASIC under the trace code. They executed correctly, although a little slower than normal.

The code supports 65C02 instructions without any extra coding except the BBR and BBS commands which would need some additional branch instruction support. Some 65816 instructions should work but the new instructions which change flow of control would fail and it doesn't understand the variable length of instructions depending on the CPU mode (but it would be quite straightforward to add).

This new trace function should prove useful for debugging future code I write. As always, the code can be found here.

Tuesday, July 10, 2012

Android version of POM1 Emulator

I earlier talked about the POM1 Apple 1 Emulator. John Corrado recently ported it to Android so it runs on Android devices like phones and tablets. It's quite cool to see Apple 1 code running on a phone. It's also quite shocking how much computer power has improved - my phone has at least 1000 times the computing power and resources of the Apple 1.

Below is a picture of JMON running on my Android phone:

POM1 Running on an Android Phone
And here are a couple screen shots of JMON running on the desktop version of the POM1 emulator:

JMON Help Screen
JMON Disassembly Feature

You can get the Android version from the Google Play app store. Look for "pom1". The POM1 simulator is maintained at pom1.sourceforge.net.



I mentioned planning to add 65C02 support to the mini assembler in JMON. Well, that only took about an hour, as it only involved adding support for the two new addressing modes. It now supports 65C02 instructions, other than the BBR and BBS instructions which have a special syntax.



While I was adding 65C02 support I thought I would write a little quick reference like I did for the 65816. I've almost finished the one page document which outlines the new software features of the 65C02 over the 6502. It will be available for download here.

Monday, July 9, 2012

Implementing A Mini Assembler


One of the features missing from JMON was a "mini assembler" like the one included in the Apple II computers.

I implemented one with roughly the same features and limitations as the one in the Apple II, i.e. it assembles simple 6502 assembly language code where all numeric values are in hex and there is no support for symbols or labels.

It is very handy for writing short assembly language programs where you don't want to fire up a cross-assembler or even Krusader.

In conjunction with the disassembler you can verify the program you entered and then run it.

The code leveraged the data tables in the JMON disassembler. Most of the work is parsing the entered code to validate it and determine the addressing mode.

While I only implemented 6502 support in this first version, because it uses the tables from my disassembler, it does accept 65C02 and even 65816 instructions that use the standard 6502 addressing modes. It just doesn't yet understand the new addressing modes for the 65C02 or 65816.

A sample session is shown below, where the user entered text is in bold.

? A 6F00
6F00: CLD
6F01: CLI
6F02: LDY #7F
6F04: STY D012
6F07: LDA #A7
6F09: STA D011
6F0C: STA D013
6F0F: LDA #5C
6F11: JSR 6FEF
6F14: JSR 6F1B
6F17: BCC 6F0F
6F19: BCS 6F14
6F1B: JSR 6EE5
6F1E: LDY #01
6F20: DEY
6F21: BMI 6F1B
6F23: JSR 6EBE
6F26: STA 0200,Y
6F29: CMP #0D
6F2B: BEQ 6F38
6F2D: CMP #5F
6F2F: BEQ 6F20
6F31: CMP #1B
6F33:

It provides meaningful error messages and checks the validity of the code. Below are some error messages:

6000: LDA #1234
INVALID OPERAND
6000: LDA (1234)
INVALID ADDRESSING MODE
6000: BNE 7000
RELATIVE BRANCH OUT OF RANGE
6000: LDB
INVALID INSTRUCTION

I tested it as I built up the code, but the final test was to disassemble about a thousand lines of JMON code and then feed that back to the assembler and confirm that it accepted it and generated the same code.

I'll probably add support for the rest of the 65C02 instructions in future and maybe also the 65816.

As always, the code is available here.

Saturday, July 7, 2012

65816 Disassembly - 8 and 16 bit modes


Today I made JMON a little smarter about 65816 disassembly. It now handles 8-bit and 16-bit instructions, looking at SEP and REP instructions to determine what mode the CPU is currently in. Of course, it cannot always get this correct as it doesn't know if code could be called when the CPU is in a specified mode. It starts in all 8-bit mode. This is similar to how the CC65 assembler works in "auto" mode unless you use assembler directives to explicitly set the mode.

While I was testing this I noticed the SEP instruction was disassembled as CPX. There is actually an error in the Western Design Center manual in Chapter 19, Instruction Lists, which I had copied when I entered the op codes. The byte $E2 is SEP but is listed as CPX.

Here is sample disassembly output from JMON showing all 4 combinations of 8 and 16-bit accumulator and index register modes (I've manually added spaces to highlight where the mode changes).

JMON MONITOR 0.97 BY JEFF TRANTER
? U 60B9
60B9   E2 30       SEP   #$30
60BB   09 12       ORA   #$12
60BD   29 12       AND   #$12
60BF   49 12       EOR   #$12
60C1   69 12       ADC   #$12
60C3   89 12       BIT   #$12
60C5   A9 12       LDA   #$12
60C7   C9 12       CMP   #$12
60C9   E9 12       SBC   #$12
60CB   A0 12       LDY   #$12
60CD   A2 12       LDX   #$12
60CF   C0 12       CPY   #$12
60D1   E0 12       CPX   #$12


60D3   C2 30       REP   #$30
60D5   09 34 12    ORA   #$1234
60D8   29 34 12    AND   #$1234
60DB   49 34 12    EOR   #$1234
60DE   69 34 12    ADC   #$1234
60E1   89 34 12    BIT   #$1234
60E4   A9 34 12    LDA   #$1234
60E7   C9 34 12    CMP   #$1234
60EA   E9 34 12    SBC   #$1234
60ED   A0 34 12    LDY   #$1234
60F0   A2 34 12    LDX   #$1234
60F3   C0 34 12    CPY   #$1234
60F6   E0 34 12    CPX   #$1234


60F9   C2 20       REP   #$20
60FB   E2 10       SEP   #$10
60FD   09 34 12    ORA   #$1234
6100   29 34 12    AND   #$1234
6103   49 34 12    EOR   #$1234
6106   69 34 12    ADC   #$1234
6109   89 34 12    BIT   #$1234
610C   A9 34 12    LDA   #$1234
610F   C9 34 12    CMP   #$1234
6112   E9 34 12    SBC   #$1234
6115   A0 12       LDY   #$12
6117   A2 12       LDX   #$12
6119   C0 12       CPY   #$12
611B   E0 12       CPX   #$12


611D   E2 20       SEP   #$20
611F   C2 10       REP   #$10
6121   09 12       ORA   #$12
6123   29 12       AND   #$12
6125   49 12       EOR   #$12
6127   69 12       ADC   #$12
6129   89 12       BIT   #$12
612B   A9 12       LDA   #$12
612D   C9 12       CMP   #$12
612F   E9 12       SBC   #$12
6131   A0 34 12    LDY   #$1234
6134   A2 34 12    LDX   #$1234
6137   C0 34 12    CPY   #$1234
613A   E0 34 12    CPX   #$1234

Tuesday, July 3, 2012

DEBUG16 - 65816 Disassembler and Trace Utility


Now that my Replica 1 is running with a 65816 processor, I wanted to try a program that was more substantial than the small demo programs I had tried.

The manual Programming the 65816 Including the 6502, 65C02 and 65802 available from The Western Design Center has a chapter describing and giving the source code for a program called DEBUG16. The program can perform disassembly and instruction tracing of 65816 machine code. It is about 1700 lines of assembler code. I thought I would try porting it to my Replica 1 using the CC65 assembler.

The first step was copying and pasting the assembler listings from the PDF file for the manual. That gave me a text file with the assembler listing of the original code.

Then I stripped out the the listing portion of the file to generate an assembler source file. It needed some changes to port it to the CC65 assembler, due to differences in it's assembler directives. After making a number of changes I had a file which would assemble and I could compare to the original listing.

It turns out there are a number of typographical as well as logic errors in the listing in the manual. A Google search shows at least one other person tried getting this code to work (about 10 years ago) and noticed the errors. After some detective work I think I was able to determine what the errors were, and obtained a file which could successfully build and generated the same code as in the original listing.

The original code was intended for running on an Apple //e with a 65816 card. The Apple specific code (e.g. for input and output) was clearly indicated in the source. I made the necessary changes to the input/output code to work on the Replica 1.

Next, I wrote a small main routine to call the LIST routine which disassembles 65816 code (I had it disassemble itself). Somewhat to my surprise, it actually produced reasonable output on the first try. I found a few errors in the code, such as an instruction or two that were disassembled incorrectly. I fixed that, although there may be some issues with a few instructions. It is at least correct enough for 6502 code that I can disassemble my entire JMON program and get the same output as from the 6502 disassembler that I wrote.

A sample of the output is shown here:

00:6013   08        PHP                                               
00:6014   18        CLC                                               
00:6015   FB        XCE                                               
00:6016   08        PHP                                               
00:6017   0B        PHD                                               
00:6018   F40000    PEA     $0000                                     
00:601B   2B        PLD                                               
00:601C   C220      REP     #$20                                      
00:601E   E210      SEP     #$10                                      
00:6020   649D      STZ     $9D                                       
00:6022   A580      LDA     $80                                       
00:6024   8584      STA     $84                                       
00:6026   A682      LDX     $82                                       
00:6028   8686      STX     $86                                       
00:602A   A780      LDA     [$80]                                     
00:602C   AA        TAX                                               
00:602D   8687      STX     $87                                       
00:602F   207762    JSR     $6277                                     
00:6032   204760    JSR     $6047                                     
00:6035   208F60    JSR     $608F                                     
00:6038   20CD61    JSR     $61CD                                     
00:603B   9005      BCC     $6042                                     
00:603D   20D462    JSR     $62D4                                     
00:6040   80DA      BRA     $601C                                     
00:6042   2B        PLD                                               
00:6043   28        PLP                                               
00:6044   FB        XCE                                               
00:6045   28        PLP                                               
00:6046   60        RTS                                               
00:6047   201D62    JSR     $621D                                     
00:604A   E230      SEP     #$30                                      
00:604C   A000      LDY     #$00                                      
00:604E   A586      LDA     $86                                       
00:6050   20F761    JSR     $61F7

The other function of DEBUG16 is a trace facility that allows stepping through 65816 code and seeing the current value of registers and disassembled instructions. This code has significantly more dependencies on Apple II functions and is harder to port. I spent some time on it, but it is tricky to debug the code as the 65816 changes in and out of native mode and 8/16 bit data and index register modes, and existing debug tools I have like Krusader's mini-monitor will not work in the 65816's native mode. I set this aside to look at later.

So the current status is that the disassembly routine is working well although it has not been tested exhaustively for all 65816 instructions. The trace function has not yet been tested or debugged. The code is available here.

While I was playing with the 65816, I took the time to make a little 65816 quick reference document. It can be printed on one double-sides page, and lists the register model, new addressing modes and instructions, and some other specifics of the 65816. It is most useful if you are familiar with the 6502 and are looking for a quick summary of what is added by the 65816. You can get it here in both OpenOffice.org and PDF formats.

Tuesday, June 26, 2012

Using the 65816 Processor


The Western Design Center 65816 is a 6502 family processor. It is backwards software compatible with the 6502 and 65C02 and was used on a number of computers including the Apple IIGS.

I've been playing with one using the CPU adaptor board I built for my Replica 1.

The 65816 comes up in "emulation mode" where it is software compatible with the 6502 and 65C02. It also implements a number of new instructions, some of which are in the 65C02 and some are new ones.

You can switch the 65816 to "native mode" at any time under software control. Native mode offers 16-bit X and Y registers and accumulator, a 24-bit address space (16 megabytes), new instructions and new addressing modes. In native mode you independently configure whether the accumulator and index registers are 8 or 16-bit. Zero page (now called direct page) and the stack can be relocated anywhere in memory.

The chip is not electrically compatible with the 6502 or 65C02. The 65802 was plug-in compatible with the 6502 but is no longer being made. The 65816 is almost compatible. The adaptor I constructed makes it compatible, or at least compatible enough for the Replica 1.

There are some limitations of the adaptor: the system still only has 16 address lines so 16MB addressing is not possible. The extra 8 high order address lines are ignored. Some hardware pins are also not supported, such as SO and SYNC, but these are not used on the Replica 1.

The only compatibility issue I have run onto is with the CFFA1 compact flash adaptor. It gives an "I/O" error. I suspect it is either due to instruction timing differences or more likely the timing of the clock signals generated by the adaptor is not quite right. I need to investigate further.

Having 16-bit registers is a nice luxury and you can still use 8-bits when you need it, by switching modes, which can save speed and code size.

There are even two new memory copy instructions which can copy a range of memory, up to the full address space, in a single instruction.

I wrote three small demo programs, available here. They compile with the CA65 assembler which fully supports the 65816 instruction set. It even has a "smart" mode where the assembler tracks whether the CPU is in 8 or 16-bit accumulator and index registers modes and generates the code accordingly.

Demo 1 uses some of the new instructions in emulation mode and then switches to native mode, first with 8-bit accumulator and index registers, and then switches to 16-bit. What can be confusing is that an instruction like PHA can push 1 or 2 bytes on the stack depending on the mode selected. An instruction like LDA #$1234 is only valid in 16-bit accumulator mode. As you can imagine, existing 8-bit 6502 machine code will soon break if run in 16-bit mode.

Demo 2 uses the MVP (MOve Positive) instruction. First it copies an overlapping range of memory, demonstrating how it can be used to fill a range of memory, in this case with zeroes. Then it does the more commonly uses copy of a range of memory from one area to another. With this single instruction you can move any amount of memory up to the full 24MB address space, taking 7 cycles per byte copied.

Demo 3 is an example taken from the Western Design Center manual which determines the CPU type: 6502, 65C02, or 65816. I extended it to be a complete program which displays the result on the Replica 1.

Links

Here are some useful links related to the 65816:

  1. http://en.wikipedia.org/wiki/WDC_65816/65802
  2. http://www.zophar.net/fileuploads/2/10538ivwiu/65816info.txt
  3. http://www.defence-force.org/computing/oric/coding/annexe_2/
  4. http://www.smwiki.net/wiki/65c816
  5. http://www.zophar.net/documents/65816.html

The definitive manual is Programming the 65816 Including the 6502, 65C02 and 65802 and is available as a free download from Western Design Center's web site, as is the data sheet.

Debugging Tips for 6502 Programing


After working on some 6502 assembler code recently I was thinking about some useful tips for debugging that I could pass on. Here are a few thoughts based on my experience. Many of these are not specific to the 6502 but valid for assembly language or any software debugging in general.

First, here are some suggestions on things to to to minimize your time spent debugging:

1. Use a cross-assembler

While some programmers can write machine code in their head and change code in memory on the fly, with assembler code you can't afford to make simple mistakes like entering the wrong hex code for an instruction. For any significant amount of code I recommend you use a cross-assembler (or at last a resident assembler, like Krusader).

2. Comment your code

It really helps to comment code, even if you are the only person who may ever look at it. A few weeks or months from now you may not understand what your code is doing if it is uncommented. As compared to high-level languages like C or C++ (or BASIC), I think it is good practice to comment almost every line of code, with additional comments describing what each routine does and tricky features and algorithms, etc. Here is an example:

; Get character from keyboard
; Returns character in A
; Clears high bit to be valid ASCII
; Registers changed: A
GetKey:
        LDA KBDCR               ; Read keyboard control register
        BPL GetKey              ; Loop until key pressed (bit 7 goes high)
        LDA KBD                 ; Get keyboard data
        AND #%01111111          ; Clear ms bit to convert to standard ASCII
        RTS

3. Use a source code management system

Even if you are the only person who may ever use your code, using a source code management system will help you keep different versions of your code during development. This is really useful for the times when you break something that was previously working and you need to figure out what changed. If you use a remote server it also protects you against losing all your work due to human error or hardware failure. There are many services now like github.com, many of which are free for free software projects, that will host your code so you don't have to set up a server.

4. Build up and test small routines

Don't write several hundred lines of code and then attempt to debug it. Write code in small routines and test them individually. It is much easier to debug and your code will likely end up being more modular as well.

5. Do a desk check

A desk check is a manual process of running through your code, as if you were the computer, verifying that it works correctly. It is often helpful to actually step through the code and keep track of values of variables and registers on paper. You will often find errors in your code this way and can more efficiently find and correct the problems.

I have to admit that I sometimes only go back and do a desk check when my code doesn't work the first time (which is usually the case).

6. Print statement debugging

Often you need to figure out where your code is going, and what the values of certain variables are. A tried and true method of debugging is to put instructions in to print information at key points in the code.

You may want to write functions that can print strings and 8 and 16-bit values that you can call for this purpose. In simple code it may be enough to just print single characters or values. If your hardware is such that you don't have a device to send characters to (screen, serial port, etc.) then even a LED or output port can be used to output debug information.

7. Use a simulator.

If you don't have a good debugger on your system you should consider using one of the available 6502 simulators to run and test your code. They may provide a better environment for debugging and testing and eliminate the possibility of hardware problems.

8. Use a debugger

On the Replica 1 the Krusader assembler provide a "mini-monitor" which lets you change registers and single step through code.

My JMON monitor  also has a breakpoint feature that works in conjunction with the mini monitor.

An assembler listing generated by your cross-assembler is also very helpful when single stepping and using breakpoints so you can relate the code to addresses.

Common Errors

Here is a list of what in my experience are some of the more common errors made, even by experienced programmers, when writing in 6502 assembler.

Off by one errors


This is the classic error where a condition test is off by one, such as a loop which runs one time too few or too often.

Branching on the wrong condition

It is easy to use a "BEQ" when you meant "BNE" and hard to notice the error when looking at the code you wrote. Good comments can help here.

Forgetting to clear/set carry before addition/subtraction

This is specific to the 6502 and most programmers soon learn not to make this mistake.

Use # when not needed or missing it when needed

It is easy to forget to use immediate addressing mode mode when that is what you intended or inadvertently use immediate addressing when you shouldn't. For example, the two code examples below are probably wrong but you can easily overlook the mistake, particularly in your own code:

  LDA '$'               ; probably should have been #'$'
  JSR PrintChar


  LDA #VAL              ; if VAL is a memory location, this is wrong
  JSR PrintByte

Registers being changed by called routines

A common error is to call a subroutine and forget that it changes some registers containing values that you subsequently use. I try to always document what registers are changed and try to preserve all registers in code unless I need to optimize them for efficiency.

Conflicts in memory locations (usually page zero)

This is a common error, especially when calling other code that might use memory locations used by your code.

Branching to the wrong part of loop

It is easy to branch to the wrong location in a loop. How many times does the code below run through the loop?

loop: LDX #10
      DEX
      BNE loop

I recently had an error like this (but a little more subtle):

loop1:
        JSR GetKey              ; Get character from keyboard
        CMP #CR                 ; key pressed?
        BEQ EnterPressed        ; If so, handle it
        CMP #ESC                ; key pressed?
        BEQ EscapePressed       ; If so, handle it
        JSR PrintChar           ; Echo the key pressed
        STA IN+1,X              ; Store character in buffer (skip first length byte)
        INX                     ; Advance index into buffer
        CPX #$7E                ; Buffer full?
        BEQ EnterPressed        ; If so, return as if was pressed
        BNE loop                ; Always taken

You can ignore most of what the code is doing. The problem is the last instruction. I meant to branch to label "loop1" but I branched to "loop", which was in a completely different routine (so it assembled okay). In part it happened because I copied and pasted the code from a similar routine and then changed it but left the wrong label. The program ran but the behaviour left me scratching my head and I had to single step through the code before I realized the problem.

Here are some additional errors which in my experience are less common but you should watch out for:

Pushing data on the stack and not correctly restoring it

A particularly bad error is pushing data on the stack and then doing an RTS, which will cause your code to return to the wrong address.

Leaving the CPU in decimal mode

If you use decimal mode, be sure it set it back to binary mode when done.

Jump indirect across page boundary

The 6502 has a bug when using jump indirect across a page boundary. The 65C02 CPU fixes this.

There are many good books on 6502 programming, some of which are freely available on the Internet on sites like http://www.6502.org.

A good reference on 6502 hardware and software advice that was recently posted on the 6502.org forum is here.