Monday, June 17, 2019

Dexter Sony LDP-1450 bug finally found and fixed!

Some of you know that I had to roll back a Dexter firmware upgrade a while ago due to that game Crime Patrol not working correctly with the update.

Well, I've been working behind the scenes to figure out what the bug was and pulling my hair out in frustration looking at my code.

It turns out that the bug had nothing to do with my changes that caused the problem but instead was a buffer overflow bug in some other code that hadn't been a problem by sheer luck :)

Once I added some new serial port code, this buffer overflow was overwriting my memory.  I finally had to attach an AVR Dragon (AVR programmer and debugger) and set a memory breakpoint to catch the problem.

Here is the code that caused the problem.  It's part of the LDP-1000/1450 interpreter:

uint16_t g_ldp1000i_tx_buf[12]; // this should be small enough so as to not waste space but big enough to hold things like current frame number
uint16_t *g_ldp1000i_pTxBufStart = 0;
uint16_t *g_ldp1000i_pTxBufEnd = 0;
const uint16_t *g_ldp1000i_pTxBufLastGoodPtr = (g_ldp1000i_tx_buf + sizeof(g_ldp1000i_tx_buf) - 1);

The fix is to change the last line to:

const uint16_t *g_ldp1000i_pTxBufLastGoodPtr = (g_ldp1000i_tx_buf + (sizeof(g_ldp1000i_tx_buf)/sizeof(uint16_t)) - 1);

The problem with working in C is that these types of mistakes are easy to make and the compiler often won't even warn you about it.  This is the price of working with lower level languages :o

Using the sizeof keyword is kind of dangerous because it always returns a value in bytes which doesn't work when your pointer is a uint16_t :)  I still use sizeof all over the place, though, because most of my pointers are uint8_t's :)

For future reference, when adding to a pointer, if you are going to use sizeof, you need to divide by the size (in bytes) of the element that makes up the array.  In this case, the TX buffer is 12 2-byte elements, so sizeof would return a 24 (12*2 is 24).  But when adding, I actually wanted to just add 12, not 24, because I wanted to add the number of elements, not the number of bytes.  So I needed to divide by the number of bytes per element (2 in this case).

After some testing, I expect to finally release some new firmware for Dexter in preparation for officially supporting the European version of Dragon's Lair (woohoo!).

Friday, May 24, 2019

How to Dockerize ld-decode (rev5)

If you are interested in the Domesday Duplicator, you may have come across the problem of installing the ld-decode software.  This is much easier using Docker because you can just use the Dockerfile that I already created.

Step 1:

Save the following text to a file called 'Dockerfile', in an empty subdirectory.

# known to work with 18.04, other versions may have incompatibilities
FROM ubuntu:18.04

ENV DEBIAN_FRONTEND noninteractive

RUN apt-get update && \
    apt-get -y -qq install apt-utils sudo && \
        apt-get -y -qq install locales && locale-gen en_US.UTF-8 && \
    apt-get -y -qq install git \
        libopencv-dev \
        libfann-dev \
        python3-pip \
        python3-tk \
        clang \
        imagemagick wget

# more schlop to install
RUN apt-get -y -qq install libqt5charts5 libqt5charts5-dev qt5-default unzip

# create a normal user so we're not running as root
RUN export uid=1000 gid=1000 && \
    mkdir -p /home/developer && \
    echo "developer:x:${uid}:${gid}:Developer,,,:/home/developer:/bin/bash" >> /etc/passwd && \
    echo "developer:x:${uid}:" >> /etc/group && \
    echo "developer ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/developer && \
    chmod 0440 /etc/sudoers.d/developer && \
    chown ${uid}:${gid} -R /home/developer

# switch to user so it installs from the user's context
USER developer
ENV HOME /home/developer

# python3 schlop
RUN pip3 install numpy pandas scipy matplotlib

# set user's home directory as current directory because that's where we'll do work
WORKDIR /home/developer

# clone and build the rev5 commit
RUN wget https://github.com/happycube/ld-decode/archive/8e8b9f2c18136a1bcdbd3d659d72e42e23135771.zip
RUN unzip 8e8b9f2c18136a1bcdbd3d659d72e42e23135771.zip
RUN mv ld-decode-8e8b9f2c18136a1bcdbd3d659d72e42e23135771 ld-decode
RUN rm 8e8b9f2c18136a1bcdbd3d659d72e42e23135771.zip

RUN cd ld-decode && make && cd tools && qmake && make all && sudo make install



Step 2:

Build docker image using this command:

docker build -t lddecode_rev5 -f Dockerfile .

Step 3:

Run docker image using this command:

docker run --rm -v $HOME:/shared -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY -e "QT_X11_NO_MITSHM=1" -ti lddecode_rev5 /bin/bash

From inside the image, the /shared folder will point to your native host's home directory.

Follow instructions here for usage.  Also, check out the "ld-analyse" UI app, it is very slick.

The nice thing about using the docker container is that you don't have to worry about installing a bunch of ld-decode dependencies to your native host operating system.  To uninstall, you simply remove the docker image.  Also, you can run more than one container in parallel if desired.

Friday, March 1, 2019

My ironic story involving a Triangular Scale

So I was mentioning that I had mis-measured the dimensions on the Dragon's Lair ROM board (see previous blog post) and Shaun Wood suggested that I look into getting a Triangular Scale.

He linked to this one: https://www.staples.com/Staedtler-Mars-12-Architect-s-Triangular-Scale/product_274746

In case the link expires, it is showing a "Staedtler Mars 12" Architect Triangular Scale (987 19-31BK)".

The picture (if you click on it) clearly shows that an inch is divided into tenths which makes for convenient PCB measuring since PCB manufacturers often use tenths of inches as their scale.

Well, I tried to find this piece on Amazon for free shipping and couldn't.  So I just googled it and found that an Office Depot local to me (on my way home, in fact!) carried it.  So I thought "Great!"

I went to the Office Depot, walked inside and quickly turned down a random isle so that I wouldn't attract attention.  (For some reason, I kinda get nervous about an employee walking up to me and asking if I need help finding anything.)  So I went down a random isle, pulled out my phone, and pulled up the link that Shaun Wood had provided.  I took note that it was the model "98719-31BK" then said to myself "Ok, now to find where it is in this store!"

I looked up from my phone and literally right in front of me was what I was looking for.  Haha!  I've never had that happen before: going down a random isle and winding up exactly where I wanted to be.  That's the first irony of the story.

The second irony is that as I examined the "98719-31BK", I noticed that it was divided into 16th's , not 10th's.  "What the heck?" I muttered to myself, as I looked at the back.  On the back of the packaging, it said that the 98719-31BK had standard 'ruler' type divisions such as 1/8, 1/4, 3/16, 3/8, 1/2, etc.  And I also noted that the similarly branded 98719-34BK was the one I actually wanted, which was divided into 1/10, 1/20, 1/30, etc.

"Oh, great," I grumbled.  "I came all this way to find the 98719-31BK only to learn that it's not the one I even want!"

Then I looked up and right next to the 98719-31BK was hanging a 98719-34BK, the very item that I wanted!

I felt kind of bemused.  Shaun inadvertently links me to the wrong item but it has the right picture.  I go to the Office Depot to get the wrong item (unknowingly) only to find out that they have the right item right next to the wrong item.  And as a bonus, I randomly walk right up to it without even paying attention to where I am going.  It felt awesome and kind of bewildering all at the same time.

That's all my story.  Good day.

Friday, February 22, 2019

Been learning KiCad (Dragon's Lair ROM PCB created to help me learn)

After I discovered that my Eagle v7 license only allows PCB sizes of something like 6" x 4" (I was disgusted), I decided to learn KiCad so that I could make larger PCBs.

Needing a simple and easy PCB to start with, I decided to reproduce the Dragon's Lair ROM board which is very basic.  All it has is a connector, five EPROM sockets, and some capacitors.

Here's what I ended up with.  I am pretty happy overall with the tool, although I did a find at least one feature that Eagle has that KiCad doesn't have that I am missing.  Still, I think KiCad may be the overall winner between the two considering how far astray Eagle has gone these days.



(here's the original for reference)

Monday, February 11, 2019

Added a new molex connector to my Electrohome G07

Someone had cut off the original molex power connector for this G07.  I studied the connector for another G07 that I have in my Dragon's Lair and found what I believe is a compatible replacement.

A small victory, but at least it was a mini project completed.


Tuesday, January 1, 2019

Digilent Discovery Quick Howto

When I haven't used my Digilent Digital Discovery logic analyzer for a while, I kinda forget how to use it.  This logic analyzer is really nice because it's relatively cheap but can capture 32 channels (!!) and has some pretty decent software to help me visualize my data.  The only real downside that I've found is that it doesn't stream so you can't have arbitrarily large samples.  This is the one killer feature of the Saleae which prevents me from saying that the Digital Discovery wins in every category.  However, it does have a decent buffer size especially for 'slower' capture speeds like 1 MHz which is usually plenty for the old tech that I like to study.

Without further ado, here are my notes (to myself) for how to set up the software to make the logic analyzer do what I want.  And a bonus youtube video at the end illustrating all of it.

----------------------

Click "Logic"

Change mode to "Record"

Click + to add channels
If adding multiple lines, choose Bus, otherwise Signal

If using trigger, change trigger dropdown to 'normal'.
Else, set it to 'none'.

Click "Config"

Choose Rate (I like 1 MHz minimum)
Uncheck 'noise'
Set 'base' to how much time you want to capture. 'Samples' will be auto computed.  Note, streaming doesn't seem to be supported, so the higher the sample rate, the smaller the sample size.

If using trigger,
Set trigger to 10% or less.  10% will capture 10% of data before the trigger happened which is often the most useful for me.


Important notes about triggers:

Triggers can be confusing.  I spent several minutes being horribly confused by this situation:




I wanted to trigger when the data lines had a value of 0x10 and when M1 was low (a Z80 instruction).  It appeared to me that what was happening was not a valid place to trigger.  However, upon closer inspection, it actually is valid because for a brief snapshot in time, my trigger criteria had been properly met.  To fix the problem, I needed to change the M1 trigger to be a rising edge instead of simply a value of 0.

My advice is to try to use falling/rising clock edges as part of your triggers.

When capturing Z80


If capturing data lines to try to find an instruction, capture on M1 (or RD) going high in addition to isolating the data bus.

If capturing address lines to try to find an instruction, capture on RD going low in addition to isolating the address bus.