Sunday, January 4, 2015

Apple On The Bench

So, my annual goofing-off and retrocomputing bacchanalia is coming to an end.  Tomorrow I will have to reacquaint myself with the dayjob and starting being a lot more responsive to email and such.  But before I get buried by my email, I thought it would be worthwhile to post another update on my Retrochallenge progress so far...

Toying With Graphics

Using a monitor program makes experimenting with hardware really easy.  Manipulating memory or flipping bits in hardware registers is nearly trivial, making it very easy to fiddle with what the system offers.  I took advantage of this to experiment with the graphics modes on my Apple II.  I used the monitor program to experiment with setting different colors on the screen, to change between the text and graphics modes, etc.  This is a great way to get a feel for how things work.

During my experiments, I was reminded of the peculiar way that screen memory is arranged on the Apple II.  One might expect that the data for the first pixel on the second line of the display would immediately follow the data for the last pixel on the first line, but on the Apple II that is not the case at all.  This is a by-product of a simplification in the Apple II hardware design, but it certainly complicates things when writing software to plot graphics to specific lines on the screen.  If you have ever noticed the "window blinds" effect when loading a graphic on an Apple II screen, you are observing what it looks like to write to the Apple II screen when accessing memory locations in a straight linear fashion.

Clearing Lines In On-Screen Order
As a coding experiment, I wrote something to blank-out parts of the screen in the order of lines as they appear on the screen rather than how they are stored in memory.  The algorithm for this wasn't too tricky, but it did require a bit of code to do some bit manipulations and to simulate what are essentially a pair of multiplications.  Even after some optimization, the code to calculate the base address of a line, to write the data for that line, and to loop through the requested lines took almost 100 bytes!  In a game, this sort of thing may merit a look-up table for finding line base addresses in the video buffer...

Unobstructed View

As I mentioned in an earlier post, I am redirecting the Apple II console through the serial port so that I can drive the Apple II from my development machine.  This works fine, but by default the output continues to be sent to the screen too.  That is fine when I'm only accessing the monitor program, but it is a problem at least for low resolution graphics mode since the text and graphics screens share the same memory -- typing commands messes-up the low-res graphics screen!  What to do?

There might be a way to convince the Apple II to stop sending output from the monitor program to the screen, but right now I don't know how to do that.  Fortunately, the Apple II actually maintains two separate screen buffers and the monitor program only modifies one of them.  Which buffer gets used for graphics output is determined by a set of registers in the Apple II that are called "soft switches".  By using the right "soft switch" to change the graphics to use the other screen buffer allowed me to do graphics experiments from the monitor program without messing-up the graphics on the screen.

Reading Log

I am still working on Assembly Lines: The Complete Book.  I have completed reading volume 1 and the original appendices, which should be equivalent to reading Assembly Lines: The Book (i.e. the original version).  So as a 6502 programmer, I am now as qualified as a young John Romero!  At least, that is how I interpret his quotation from the back cover... :-)

But seriously, there is plenty more to read.  With that said, I am feeling a bit more qualified to code for the 6502.  Plus, I am learning a bit about Apple II architecture and such -- I found some interesting stuff online about timing code to the vertical blank interval on the Apple IIe, IIc, and IIgs (all done differently).  I'm still not sure what coding project I will do, but some options are coming into focus.  If you want to read more about it then I hope you will stay tuned!

Friday, January 2, 2015

Out Of The Gate

Ending the second day of 2015, I think I've made a healthy start on my Retrochallenge project!  The goal is to familiarize myself a bit with the Apple II line of computers and learn enough about programming the 6502 to be dangerous...or something.  I have had a few bumps along the way while establishing my development environment, but now I think I've got a good level set...

Serial Offender

I like to use a monitor program when developing code for retro computers or any other sort of "small" target system.  The low level interface a monitor program offers is great for taking full control of a system, manipulating hardware registers, loading code, etc.  Fortunately for me, the Apple II machines actually shipped with such a monitor in the built-in ROMs!  Even better, the Apple II makes it easy to control the system over a serial port...or so it seemed!

Like many people with an interest in retro computing, I'm old enough to remember when a serial port was a gateway to the world, or at least a gateway to the BBS on the other side of town.  I'm no stranger to RS-232 communications, but talking to the serial console on the Apple II sprouted a few extra gray hairs on my head.  "IN #2" and setting the baud rate caused the Apple II to accept input over the serial port, but "PR #2" only produced junk on my terminal screen.  Adjusting the communications parameters seemed obvious, but none of the sane options worked.  Ultimately I used settings of 7 data bits and "mark" parity, but 8 data bits and/or "space" parity seemed to work just as well.  I wouldn't be surprised if technically I'm still using the wrong values and just getting lucky...?

That almost sorted the physical setup, except that my TV is on one side of the room and my desk is on the other side of the room.  I could use a long cable, but that can be a bit awkward.  Bluetooth provides a convenient means of replacing a cable with a wireless connection, and I happen to have an unused Bluetooth<->RS-232 adapter available.  Deploying that device made the required connection from across the room.

Super Serial Over Bluetooth
Varies By Model

Not all Apple II machines are the same!  I knew that, of course.  But I did not appreciate just how much variation there is even among similar models.  What illustrated this for me was trying to run the Apple II mini-assembler.  "Assembly Lines: The Complete Book" describes starting the mini-assembler by typing "F666G" from the monitor prompt.  Unfortunately, this simply didn't work.

I was under the impression that the Apple IIe included the mini-assembler in its ROM.  But deeper research uncovered that this was only true for the "Enhanced IIe" models.  Closer inspection revealed that my IIe was in fact a non-enhanced model.

Not An Enhanced IIe!
My research also indicated that the mini-assembler _is_ included in the ROM for the Apple IIc.  I swapped the IIe in my setup for a IIc, but "F666G" still didn't work!  Again I consulted the Google, eventually showing that in the later ROMs (like the IIc and the Enhanced IIe) the mini-assembler is entered by typing "!" at the monitor prompt (rather than "F666G").  After toying with the mini-assembler, I returned the IIe to my setup mostly because the Super Serial card in the IIe does not require setting the baud rate after every "IN #2" command.  The mini-assembler is useful, but significant coding will require a real assembler.

Peaceful Assembly

I'm not sure what assembler most Apple II coders use these days, but for now any 6502 assembler that produces raw machine code will work for me.  My development platform of choice is Fedora, and it so happens that there are (at least) three 6502 assemblers available in the Fedora repositories.  I chose to install ATasm, mostly because I was somewhat familiar with it from earlier Atari 2600 dabbling.  I realize that ATasm is geared toward the Atari 8-bit line of computers rather than the Apple II, but for now its raw output format will suffice.

How do I get the assembled code onto the Apple II?  Well, I wrote a little Bash script to take the machine code binary from the assembler and format it into commands that can be typed into the Apple II monitor program.  I then copy that command text and paste it into my terminal window connected to the Apple II -- voila!  In the long run I may want a different or more traditional solution for loading my programs on the Apple II, but this works great right now.

So, now what?  Well, I still have a lot of pages left for me to read in "Assembly Lines: The Complete Book".  Along the way there will probably be some fun code experiments.  If you want to see what happens, then I guess you will have to stay tuned!

Wednesday, December 31, 2014

RC2015/01 Contest Entry

Once again the turn of the year approaches, bringing with it a Retrochallenge event.  Generally, for Retrochallenge I want an entry that scratches an itch of some sort while maintaining the desired level of "why would anyone do that?"  I had a few items under consideration, but none felt quite right for a variety of reasons.  Also complicating things are some home repairs that will likely require us to vacate our house for several days sometime this month -- not very friendly to a hobby project with a deadline! :-)

As fate would have it, a few things came together to give me a bit of a "sign" as to what the project should be:
  • A recent eBay search led me to taking an interest in "Assembly Lines: The Book" by Robert Wagner;
  • Shortly thereafter I became aware of "Assembly Lines: The Complete Book", which is a modern reprinting and extended edition;
  • I ordered the book from Lulu.com, and it arrived yesterday just as I was getting desperate about finding a Retrochallenge project.
While I have dabbled a bit with programming the 6502, that has been confined to toying with the Atari 2600.  Similarly, my experience with the Apple II is limited mostly to some LOGO programming back in elementary school and a few more recent retro computing experiences here and there.  Clearly, there are a couple of related gaps in my retro computing prowess that I would like to address...

So, my project will be an attempt to read and absorb "Assembly Lines: The Complete Book" with the goal of writing some sort of program for the Apple II series of computers.  I'm not promising anything as good as Threshold.  But if I succeed, then maybe I can go to KansasFest this year without feeling like too much of a poser!

Wanna see how I do with this?  Then you'll just have to stay tuned... :-)


Tuesday, July 30, 2013

RC 2013 SC Wrap-Up

Once again, a Retrochallenge event draws to a close.  As usual, I have greatly enjoyed participating in this event.  Setting some deadlines is a good way to motivate progress on a project, even silly ones involving retro computers.  Plus, it is always great to have the recognition and the feeling of accomplishment that comes from having the audience that comes with participation in a great event!

Recap

My project for this month was to adapt the Dunfield Micro-C compiler for building code to run on the CoCo.  Initially I just wanted to make it relatively simple to use the tool for building simple CoCo programs.  After some initial victories, I went further by supporting a variety of ways for loading and starting such programs.  I also now support several options for passing data between C programs and the built-in Color BASIC on the CoCo.  To prove the point, I implemented a couple of non-trivial CoCo programs in C -- an animated clock display and a solver for Sudoku puzzles.  Although I have more in mind to do on this project, I am extremely happy with the results as they stand right now!

Benefit

The CoCo community has a bit of a schism between users of OS-9 (or its descendant Nitros-9) and those that mostly stick to the Disk Extended Color BASIC (DECB) environment.  For sure, most CoCoNuts have a foot in each camp.  Yet, most prefer one or the other.  Each option has its own merits, but those that prefer the DECB environment usually cite both simplicity and the direct control of the CoCo's hardware as important strengths.

Both camps have both BASIC (including BASIC09) programmers and assembly language programmers.  The OS-9ers have also enjoyed a C compiler for decades, but the DECB-based C compilers are mostly the stuff of barely remembered advertisements in The Rainbow.  Now, the DECB crowd has at least the beginnings of another option!

Onward

I have really enjoyed using C to program for the DECB environment.  So, I am planning to continue this project in the hopes of enabling more CoCoNuts to have the same opportunity.

As I have pursued this project, I have generated a list of more TODO items than I have had a chance to pursue.  These include a few more startup options, code libraries, hardware drivers, and the like.  I expect to hit many of these over the next few weeks or months.  If nothing else, then I should have something together by next year's CoCoFEST!

Normally I would like to have more code to release at this point.  Unfortunately, I haven't had a chance to pull a release package together.  Since this project depends on the Dunfield compiler distribution, I want to make sure that I can release something as clean as possible to make the distinction clear between my code and the Micro-C package.  Also, I want to put together at least some minimal documentation on how to put everything together in order to start building CoCo programs!

So, for now you will have to make do with the bits and pieces that I have released along the way.  I hope that whets your appetite for more.  If you want to collaborate on advancing this project, then feel free to contact me and let me know so.  And, in any case, be sure to stay tuned... :-)

Sunday, July 28, 2013

Sudoku Solver

My Micro-C for CoCo project is showing some real strength!  Yesterday, in just a couple of hours I was able to crank-out a non-trivial C program to solve a popular style of number puzzle.  That was a lot of fun!  Moreover, it was simpler than trying to implement the same thing in pure assembly language and the resulting program ran a lot faster than it would run if it were written in Color BASIC.

Sudoku

In the past decade or so, Sudoku puzzles have become as commonplace as the venerable crossword puzzle.  The use of numbers seems to have a special appeal for some folks, and it has been quite common for people to implement solvers for these puzzles as a programming exercise.  Quite a lot of discussion is available over various algorithms for solving such puzzles, and implementations of these algorithms are quite numerous.

A friend of mine had such a project a while back.  When he learned of my current project, he jokingly suggested that I should try to compile his solver for the CoCo.  I think that his project implemented some clever algorithm or another -- I never saw his code, so I don't know if it would be out of the question for the CoCo or not.  But, I did find a brute force algorithm that seemed simple enough to implement.

Recursion

If one makes the distinction between computer scientists and computer engineers, one often finds that the scientists love recursion while the engineers are more skeptical.  To be sure, recursive algorithms often lead to elegant programs that are powerful, expressive, and succinct.  On the other hand, language implementations often impose practical costs on function call stacks that can grow very deep with recursion.  The engineers...ahem...are correct, of course!

Recursive algorithms are only safe when there is a finite and tolerable limit to the recursion.  In the case of Sudoku, there are only 81 positions on the game board to evaluate.  My implementation uses a recursive, brute force algorithm, and it runs without issue in the 8K of RAM that I'm currently allocating for the code and the stack.  It will probably run in half of that or even less, but I haven't tested to find out.

Load 'Em Up

A puzzle solver isn't of much use if it always solves the same puzzle.  On the other hand, writing a puzzle editor doesn't sound like much fun for the amount of effort involved.  What to do?  If only the CoCo came with some sort of built-in editing facility that could help with such tedious tasks...hmmm...

Rather than delving into the minutiae of building a Sudoku editor in C, I decided to let BASIC do the work for me.  I wrote a short BASIC program that first reserves space for the C program and loads that there.  The BASIC code then READs the Sudoku game setup from the included DATA statements and pokes that into memory where the C program can find it.  The puzzle can be changed by simply editing the DATA statements to reflect the new puzzle.  It would be hard to make things any easier, and IMHO it isn't worthwhile to do so.


Burlington Mini Maker Faire

Where I live, we have a little "maker club" called the Alamance Makers Guild.  Last year we held a mini Maker Faire at the local mall, and we will do so again this year on August 17, 2013.  At last year's event, Fahrfall made a good showing and at least some people seemed to enjoy seeing that and my video player for the CoCo3.  I think the Sudoku solver will make its public debut there this year, and I am planning to make a little contest out of it.  I'm thinking that I will challenge humans to see if they can solve a Sudoku puzzle before the CoCo can do it.  I might even make them edit the BASIC program with the Sudoku data themselves before they run it!  Well, it sounds like fun to me...

This seems like a high note on which to end this summer's Retrochallenge event.  I probably won't be doing much more technically on this project before the end of that event.  I do, however, plan to be back with a more reflective post as a wrap-up.  Until then, please do stay tuned...

Friday, July 26, 2013

Marking Time

It is time once again for another exciting update on my Micro-C for CoCo project.  It has been a busy week for me here in North Cackalacky!  Unfortunately for me, it has mostly been a "work" kind of busy...  Nevertheless, I have been able to make a little progress on my project.

Pak It In

Like many machines of it's era (e.g. the Atari 2600), the CoCo had the option of using software distributed on ROM cartridges.  The clever marketing folks at Tandy marketed this as "Program Pak" software...  In any case, there are advantages to this software format.  So, it might be nice to distribute compiled C programs the same way.

Relocating the compiled code to the ROM cartridge address space is the obvious first step.  An added twist is the question of where to put the variables.  Obviously, storing "variables" in ROM is of limited value.  Luckily, the Dunfield library already provides for allocating variables in a different address range from where the code resides.  Yet another variation of the startup code allows for selecting this configuration.


Many programs require the use of interrupts for proper operation.  But, handling interrupts requires machine-specific accommodations that aren't part of the standard C language.  Many compilers provide mechanisms for implementing interrupt handlers in C, and Micro-C is no exception.  Unfortunately, the default mechanism provided with the Micro-C package generates code to hook the 6809's interrupt vectors in a ROM image.  That is fine for use in an embedded system, but it won't work with the CoCo.

The CoCo ROMs redirect the interrupt vectors through a secondary set of vectors in RAM.  Using the stock Micro-C interrupt implementation as a guide for interfacing with the compiled code, I implemented a CoCo-compatible version.  My implementation uses a macro to output some inline assembly code in order to establish some code labels and to provide a 'trampoline' function.  The trampoline function calls the C interrupt handler and then uses an RTI instruction to resume normal operation of the CPU.  I also added some macros to make it easier to point the secondary interrupt vectors at the appropriate handlers in the C code.

Time Flies

One of the few timing sources on the CoCo is the ~60 Hz Vertical Sync (a.k.a. "Vsync") interrupt.  With the code described above I was able to build a simple clock program that keeps time by counting Vsync interrupts.  I also used an inline assembly macro to provide access to the SYNC instruction.  This allowed me to properly time a colorful border animation for the clock -- the border is timed to complete a loop in approximately 1 second.  Just for fun, I compiled the clock to run in the emulator as a ROM image.  Since I didn't bother to burn a physical ROM, I also re-compiled the clock as a BIN file to load through the cassette interface on a real CoCo.


If you experiment with running my clock demo, you will find that the CoCo isn't really a very good time keeper.  Keeping time by dead reckoning with an almost-but-not-quite 60 Hz timing source doesn't compete with the accuracy of a Swiss watch!  I toyed with a few drift compensation strategies, but so far all I've done is prove that programming the CoCo in C is every bit as much fun as it is to program one in BASIC or assembly... :-)

Anyway, I guess that is enough for now.  Only a few more days remain for the Summer 2013 Retrochallenge event.  I hope to make the most of them, but I suspect that in any case I will be working on this project well past the end of the competition.  Either way, I hope you will stay tuned!

Sunday, July 21, 2013

BASIC Instinct

As I was working on implementing a CoCo API comparable to what Color BASIC provides, I had a couple of realizations.  The first was that while such an API might be superficially familiar to some CoCo programmers, it wouldn't necessarily be a good API for anyone to use.  The other was that an API implementation wasn't actually as interesting as some other aspects of the project!

So for now, I'll leave the remainder of the API library work undone.  I may return to expanding the library later, but for now I want to hit a few more objectives.  In this episode, we will look at interfacing C programs to Color BASIC...

CLEAR Some Space

Once again we come to the problem of where to put a program in the CoCo's memory space.  This is similar to what we faced before, except that now we have to share the available memory with a BASIC program at the same time.  What needs to happen is for BASIC to give us some space to live and for it then to leave us alone.

Color BASIC is ready for us.  The CLEAR command allows us to influence how BASIC allocates memory, including the ability to set a limit on the highest address BASIC will use for its programs.  This allows a BASIC program to make room for us before loading and executing our program.

Corresponding to that, I created options in the startup code to allow the C programmer to specify what CLEAR value is being used.  This causes the C program to be compiled to run in the proper space and to allocate memory appropriately.  More importantly, it provides us an open field in which to run without worrying that we might trample on something important to our BASIC program.


CoCo programs that don't interact with BASIC don't have any way to accept anything like a 'command-line argument', so there has been no need to worry about that until now.  BASIC doesn't offer C programs a command-line either, but there are ways to pass information to our C program if we so desire.  In fact, perusal of the Color BASIC documentation reveals that there are a variety of options for passing information both into and out of C programs.

Lacking a single path to follow, I implemented a variety of options in the startup code.  These correspond to the documented options for Color BASIC to pass information to a 6809 machine language program, and they require certain variations to the 'main' declaration in the C program.  Some of those options require data structures that are foreign to anything resembling standard C, so I also knocked together a header file to describe the various data structures involved.  I posted that header file and some sample prefix files that set options for the startup code, if anyone is interested.


The Color BASIC documentation had another interesting point -- the stack provided by Color BASIC is only good for about 30 bytes of usage.  It wouldn't take many levels of function calls with arguments pushed onto the stack to burn-up that little amount of space!  Not only that, but the Micro-C library's implementation of malloc presumes that the stack is at a higher address than the heap.  The memory provided by the CLEAR command is at a higher address than the Color BASIC stack, so malloc won't work with it.

The answer is simple enough -- allocate a new stack at the top of RAM.  Of course, in order to return to the calling BASIC program the Color BASIC stack pointer has to be saved at program entry and restored at program exit.  A few more simple modifications to the library startup code accomplished this task without incident.

So, now we can produce CoCo programs written in C that either stand alone or which can fully cooperate with programs written in BASIC.  Things are coming together nicely!  There is only a little more than a week left in the Summer 2013 Retrochallenge event.  Do you want to see what comes next?  Then I guess you'll have to stay tuned!