Wednesday, January 20, 2016

6502 Learning (RC2016/1)... Video buffer sidetrack...

I got a little sidetracked while working on the KIM-Uno calculator, playing with video buffers. I had added a video buffer to the desktop Kim Uno Remix project. Ultimately, I want to make a compressed image decoder and viewer.. to draw sprites to the screen or full-screen images.

I've written stuff like this before back on the Z80 for Pac-Man hardware, so I thought it would be a fun exercise to see how something like this would be implemented on 6502. It gives me a good chance to learn addressing modes and methods for this architecture... which is very different than Z80's.

You can attempt to play along by using this web-based assembler system. I based the video buffer in KIM Uno Remix on this system.  There are a few differences though...

6502asm.com:

  • 32x32 pixels
  • 16 colors
  • Commodore 64 palette
  • starts at $0200, continues horizontally then down, starting top left
  • one byte per pixel
  • bottom nibble indicates the color ($00..$0F)
  • top nibble is ignored
  • code starts at $0600
KIM Uno Remix:

  • is 32x32 pixels
  • 16 colors
  • Modified Deluxe Paint palette
  • starts at $4000, continues horizontally then down, starting top left
  • one byte per pixel
  • bottom nibble indicates the color ($00..$0F)
  • top nibble is ignored
  • code starts at $0200
Here's the output from a small program (shown below) that shows off the palettes of the systems. The KIM Uno is on the left, and shows the very reasonable "rainbow" palette.  The one on the right shows the more convoluted "Commodore 64 palette" of the web tool.


The colored sections are 8 rows of 32 pixels across. Since there's only 16 colors, the color stripes get repeated twice along the horizontal of the screen.

The code to run the above was essentially identical on both systems but there are some tweaks to accommodate the addresses and some minor differences between the CC65 tools that I use and the web-based tool.


Here's the source code listing used for CC65, which generated the image on the left above.  You can see that it writes to two of the four banks of memory space, at $4000 and $4200, while not doing anything with the $4100 and $4300 banks, which is why we see two segments of stripes, and two segments of black in the above image. It is a very simple program that simply increments "X" and writes it to videobuffer[x].


And here's the source for the web-based tool.  I colorized it to match the above CC65/KIM Uno Remix listing.  Notice that the program is the same, although it uses $0200 and $0400 for the screen memory, skipping the $0300 and $0500 sections.  I also switched the "unnamed label" from the above code to be a label named "loop" for this one.  It apparently doesn't support that.

Saturday, January 9, 2016

KIM Calculator Update: Learning 6502 and reducing code size

One of the functions of this KIM-Uno project involves functionality similar to the stock KIM monitor.  You press buttons 0-9, A-F to enter a number (a nibble, a half byte), and it scrolls in from the right side of the display.  Usually you can only enter the address bytes (first 4 digits) or the data byte (rightmost 2 digits).  I wanted to use all 6 digits for the values entered so I needed to write my own handler for this. I decided to kinda glance at the KIM Monitor code, but I wanted to make it all on my own.

Version 1 sketch...

Version 2 sketch.

Both of the above (which didn't quite work) were basically the same as the working version (v3) which I did implement and had in the code for a week or so.  It was 46 bytes long, plus a sub function which got called 3 times that was 20 bytes long.  Not very small.  The basic procedure was this:


  1. Get the key from the user (0x00 - 0x0F), store it aside
  2. for each of the three display bytes (eg 0xMN)
    1. Store it in X (input byte)
    2. shift it to the left by 4 nibbles (one display digit)
    3. store aside this value 0xN0
    4. restore the display byte (0xMN)
    5. shift it to the right by 4 nibbles (one display digit)
    6. store aside this value now (0x0M) this is the "carry out"
    7. Add the user input key with the first stored value  0xNK and put in "X" (output byte)
    8. restore the "carry out" to "A"

That's basically it. Nothing particularly wrong with it, it works fine, but once you understand more of the opcodes available in the system, we can drastically reduce this.

I was working on implenenting one of the calculator functions "Shift left one bit" when I learned/remembered about shifting with ROL (rotate left) and ROR (rotate right) which shift the bits around, storing the one going out and the one going in using the "carry" flags bit.  The implementation of this function was super easy using this:

clc          ; clear carry bit (shift in a '0')
rol DIGIT3   ; shift data in memory location DIGIT3 one bit
rol DIGIT2   ; these take the bit shifted out and store it
rol DIGIT1   ; in the carry bit, then shift that bit in
jsr DISPLAY  ; and display it

Then it hit me, I could leverage off of this carry bit for the above process, since it basically is:

  • Shift all three bytes to the left by one bit four times (one nibble) 
  • Shove the key in to the lower nibble of DIGIT3
This change of shifting everything by one bit four times, rather than the above where I was shifting four bits three times, worked out perfectly with the available opcodes.  Here's the final code for this routine:  (INH is the third digit pair, POINTL and POINTH are the second and first digit pairs of the display respectively)

We set up a loop using "x" as the counter register, notice we set it to '4' first.  We are also doing something that I just learned about which is non-named labels, which is why you see ":" starting a line, then a "bne :-"  (branch (goto) if not equal to the previous non-named label.)

keyShiftIntoDisplay:
        ldx     #$04            ; 4 bits to shift
:       clc                     ; rol pulls from carry, so clear it
        rol     KIM_INH         ; shift this byte by 1 
        rol     KIM_POINTL      ; shift this one, carry from INH
        rol     KIM_POINTH      ; shift this one, carry from POINTL
        dex                     ; x = x - 1
        txa                     ; a = x 
        cmp     #$00            ; a == 0?
        bne     :-              ; mot 0, repeat loop

        ; now shove the content in
        lda     KEYBAK          ; restore key 00 .. 0F to A
        ora     KIM_INH         ; A = A | INH
        sta     KIM_INH         ; INH = A
        jsr     SCANDS          ; and display it to the screen
        jmp     keyinput        ; next!

Which works out substantially smaller.  It has one chunk of 13 bytes that gets run four times, for the entire code block of 27 bytes.  Quite a lot less!  I'm really enjoying learning 6502 asm for this!

The code for this project can be found on github at The LlamaCalc directory of my Projects5502 repository.  This requires the cc65 toolset to build.

Friday, January 1, 2016

Retrocomputing Challenge 2016-1: Learning 6502, KIM-Uno stuff

Starting today, I'm going to attempt to better learn 6502 asm in my copious amounts of free time for the  RC2016/01 Retrocmputing Competition.  To prepare for this, over the past year I've gotten into working with Oscar Vermeulen's awesome KIM Uno kit, as well as pushing out my own updated firmware for it in the form of my Kim Uno Remix project on github.

Part of that project was to make it more portable and make it available on other platforms.  I have a preliminary iOS build of it, as well as a QT-based desktop build of it checked in which builds on Mac, Windows and Linux.  Source at github will build for all of these, if you have QT Creator installed (along with support compilers for your system of course.) Binaries will be available eventually for all platforms.



In the above screenshot you can see some 6502 asm in the center window. I have a makefile which uses the industry(homebrew) standard(?) cc65 compiler/assembler  to assemble it into a .lst "listing file".  This file contains the original ASM as well as the machine language bytes and the addresses they sit at.  This is a lot better, imo for distribution as it can be easily trimmed (ref: unix 'cut') to the original asm, or it provides the necessary information to hand-enter it into a KIM.

The KIM Uno emulator can be seen on the leftmost window. It looks like you'd expect a KIM on a desktop to look.  There are two other windows here though.  The Video Display shows a virtual framebuffer which sits in KIM memory at $4000 (0x4000).  It is 32x32 pixels, one byte per pixel.  Only the bottom nibble is currently used in the byte, to signify one of 16 colors ($00, $01... $0E, $0F).  At compile time you can use the Commodore 64 palette, or the Amiga palette, which is based on the default colors from Deluxe Paint.  This feature is heavily influenced (copied/borrowed) from the very awesome virtual machine/programming interface available at 6502asm.com.  Theirs sits at $0200, which collides with KIM stuff, so I moved it to $4000.  Otherwise it behaves the same.

There are a couple windows not shown, including a serial terminal emulator that connects to an emulated UART in the KIM, so that you can run the chess application or what have you.  Also available is a memory browser that lets you look through the entire 64k memory space of the 6502. It allows you to have it update automatically so that you can see changes as they occur.  Very handy for debugging

Now here's where things get neat...

The window in the bottom right is for a feature I call "Code Drop".  You can take one of the .lst files mentioned above (generate one by running "ca65 project.asm -l project.lst") and drag and drop it to that window. Or you can click "Browse..." and pick it from your filesystem.  Now, when you hit "Load to RAM", it will load in that .lst file, and drop the bytes in the appropriate place in RAM, while the emulation is still running.

The "Auto ADDR seek" feature will then auto type-in for you the first address specified in the LST.  The "Auto GO" feature will do the seek, then press "GO" for you as well.

The application is also sensitive to the SIGUSR1 signal, which does the same as pressing the "Load To RAM" button.

So here's what you (I) do...

The desktop application is set to the appropriate .lst file for the project I'm working on.  It is set for "auto GO" as seen above.  Now in the makefile for the project,  it will build the .lst file, then send the SIGUSR1 signal to the application.  When I type 'make', it assembles the file, builds the lst, then triggers the emulator to reload and restart the code, essentially integrating it into my build process.

.oOo.

For the challenge, I want to use this system to make a simple integer programmer's calculator which I can run on the KIM Uno itself.  Press keys to shift in the nibbles, then switch it into a mode where i can affect the data.  Convert hex to decimal, do bitshifts, add, multiply, etc.

Monday, October 26, 2015

Sword for The Spider Ninja!



A new attraction is opening up at Winterground Fairlands! "The Adventures of the Spider Ninja"  It's an exciting attraction with Spider Ninjas, and various challenges and action and probably a lot of running around with swords.  This attraction required costuming to create something all new for the cast members.  Shown in the picture is Jasper with his uniform.  The ninja mask and spider outfit were created by Pam the Costumer specifically for Jasper's small frame.


The new swords were built using various corrugated cardboard products.

The blade was made by rubber-cementing three layers of cardboard together, with their "grain" going in different directions for strength.  The blade actually continues through the hilt and into the handle, much like a real metal sword.


The handle is just a piece of thick cardboard tubing originally from wrapping paper.  It has a smaller diameter and is stronger than paper towel tubing to accommodate the cast member's smaller hands.

The hilt was a paper towel tube, with a round hole on one side to accept the handle, and a rectangular hole on the other side to accept the top portion of the blade.



Once the blade is pushed through the hilt and into the handle, everything fit very snugly, and didn't need any additional adhesives... but just in case, and for extra strength, the hilt was loaded up with lots of hot glue, and additional glue was added around the joints from the outside.

A couple coats of plain 'ol black spray paint and then the fine detail work could be done.  Jasper added some spiders he made out of Perler beads and the sword was completed!

Monday, October 19, 2015

Major Blog Announcement!

Hi and welcome to the new readers!

Just to let you all know, this blog will be slightly changing over the upcoming months.  The focus will still be on projects that we're working on/have worked on... but for a new venue

!I've recently picked up and moved to Sklarsville, Maine and am working full time at the world famous Winterground Fairlands Park and Adventurefun Center!!!

The wonderful part of this whole thing is that being hired as the head of the "Funmagineering Gang", I am able to make posts about the various projects we're working on for the park and in our skunkworks in general. There may even be some great blue-sky projects we'll be able to share with you!

So sit back, and "Enjoy the Adventurefun!"TM

Tuesday, October 13, 2015

Nintendo DS Lite case mod



Many years ago, I bought a white Nintendo DS Lite.  I loved the form factor, the look of it and the games I could play on it.  There were a lot of games for it, and for the GameBoy Advance which I already had which I'd love to play on it.

Over time, I've gotten a R4DS card so I could play homebrew (yeah, let's go with that) and use it as a kind of PDA type of thing. I also got an EZFlash V for the same reasons. For homebrew. Because that's still a thing, right?  (The screenshot above shows the R4DS interface, which I've re-skinned to like AmigaDOS 1.3 because that's something I do.

Anyway, at some point, I got a completely transparent shell for it, which was really neat for a while.  It was a pain to move the guts over to that shell, but it looked neat for a while.  Then The upper screen failed and the touch scanner failed on the bottom.  So I replaced those.  Then the right shoulder button failed, so I replaced that... which never really worked well, as the button broke off of the main board. There just wasn't enough structure there to support it.

Fast forward a few years, and I picked up a European black DS Lite in a trade for some old GBA stuff I didn't want anymore.  That one worked GREAT, except that the screen hinge was completely destroyed.  I used that for a while, but ended up shelving it.

For a while I've been meaning to take the best parts of all of this and put together one fully functional DS Lite.


I had planned to take the top screen from the black unit, but the ribbon cable broke while I was removing it from that unit.


What I ended up with was this:
  • Case enclosures - White
  • Top and shoulder buttons, switch cover plastics - Black
  • Upper Screen - White (replacement, colors aren't perfect on it, but it's good)
  • Lower Screen - Black
  • Motherboard - Black
  • Battery - Black
  • Wifi Antenna - Black (The cable was broken on the white one)
  • Rubber feet, screw covers - Black
  • Stylus - White (Black one is on order)
I think the final form here is pretty sharp.  Best of all, it's fully functional again! Yay!

Monday, October 5, 2015

Arduino Ethernet Library Modification

I was recently working on a piece of test/demo code running on an Arduino that talked through a Seeed Studio Ethernet shield.  The standard Ethernet library will not acknowledge a connection back to the host code until it receives something from the client.  For most things, this works out just fine (HTTP, chat servers, etc) but in some cases, like for RFB/VNC servers, it must first send out something itself to the client.  The as-shipped library does not allow for this, so it required a minor hack to the library code to make this option available.

in (Libraries)/Ethernet/src/EthernetServer.cpp, we can see the following code:
  01 EthernetClient EthernetServer::available()
  02 {
  03   accept();
  04   for (int sock = 0; sock < MAX_SOCK_NUM; sock++) {
  05     EthernetClient client(sock);
  06     if (EthernetClass::_server_port[sock] == _port) {
  07       uint8_t s = client.status();
  08       if (s == SnSR::ESTABLISHED || s == SnSR::CLOSE_WAIT) {
  09         if (client.available()) {
  10         return client;
  11         }
  12       }
  13     }
  14   }
  15   return EthernetClient(MAX_SOCK_NUM);
  16 }

As you can see, it checks to see if there is a connection established (line 08), then it checks to see if there's any content available from the client (bolded line 09), and only then will it return the handle to the newly connected client. This will be called in your Arduino code like this (from the WebServer example, packed with the Ethernet library)
void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // do stuff here...
    client.stop();
    Serial.println("client disconnected");
  }
}

This loop will only make and break connections if the client is actually connected AND it has data available. For most servers, this is sufficient.  However, if you want to allow for clients that connect and then just listen, you need to do the following...

In EthernetServer.cpp, create a copy of the ::available() method, eliminating lines 9 and 11 above. I call this function ::connectionEstablished(), plopped right into the EthernetServer.cpp file, just after the ::available() method, and it is implemented as follows:

EthernetClient EthernetServer::connectionEstablished()
{
  accept();
  for (int sock = 0; sock < MAX_SOCK_NUM; sock++) {
    EthernetClient client(sock);
    if (EthernetClass::_server_port[sock] == _port) {
      uint8_t s = client.status();
      if (s == SnSR::ESTABLISHED || s == SnSR::CLOSE_WAIT) {
        // "if" statement removed
        return client;
      }
    }
  }
  return EthernetClient(MAX_SOCK_NUM);
}

Next, you need to add the method to the header file, EthernetServer.h, as seen in this snippet
class EthernetServer :
  public Server {
    private: 
    uint16_t _port;
    void accept();
  public: 
    EthernetServer(uint16_t); 
    EthernetClient connectionEstablished();
    EthernetClient available();
    virtual void begin();
    virtual size_t write(uint8_t);
    virtual size_t write(const uint8_t *buf, size_t size);
    using Print::write;
};


Now, you can call this new method like this:
void loop() {
  // listen for incoming clients
  EthernetClient client = server.connectionEstablished();
  if (client) {
    Serial.println("new client has connected");
    // do stuff here...
    client.println( "Hello, goodbye!" ); 
    client.stop();
    Serial.println("client disconnected");
  }
}