QR Code Generator for TI-99/4A
Released at TI-99/4A PNW Fest West 2016 (“Version 0.9”).
Uses Bitmap Mode (“Graphic 2”) (256x192)
with 3 Pattern Tables (6144 bytes) and 1 Color Table (2048 bytes)
Smallest QR Code (“Version 1”) is 21x21 pixels
Largest QR Code (“Version 40”) is 177x177 pixels
Learned how to build QR codes by following the very detailed Thonky.com Tutorial
To simplify the project, several limitations are in place:
- Hard-coded to use Quality Mode “Q” (QR has Low, Medium, “Q”, and High Error Correction, Q is the 2nd best). Felt “Q” (“Medium-High”) was the best compromise.
- Hard-coded to use encoding scheme for 8-bit byte data (QR has numeric-only, alphanumeric-only, Byte, and Kanji). Felt Byte was the most useful.
- Hard-coded to use Mask 1 (the bits of every even row are flipped). This is probably a bad thing and is against the QR specification. You are supposed to try each of the 8 available mask types, calculate a “penalty score” for each mask, and then, for the final rendering, use the mask that had the lowest penalty. The penalty is based on number of consecutive blocks having same color, etc. It’s designed to make it easier on scanning equipment. In reality, I don’t think it matters—everything generated by my program should be a valid QR, it may just not be the “best” QR possible.
Maximum message size using 8-bit Byte encoding with Version 40-Q is 1,663 bytes. It takes about 11 seconds to generate the 177x177 pixel V40-Q QR Code.
Message size after Reed-Solomon error correction for a 40-Q message is 3,706 bytes (or 29,648 individual bits that get drawn on QR code, not counting bits used for finder patterns, alignment patterns, timing patterns, mask info, and other format and version info).
Also tested on real console with NanoPEB, with F18A (VGA output).
Also tested on real console with NanoPEB, without F18A (composite output).
I confirmed that the QR code was readable by my Android phones even with non-F18A machines using composite output. I was somewhat worried about it because the composite output is pretty noisy on my television (dot crawl, visible colors where it should be black-and-white, etc.) It could still scan it, but it sometimes took a tiny bit of additional effort for the Android QR app to scan and decode the display.
The two Android apps I used for testing:
- QR Scanner from Kaspersky Lab (version 18.104.22.168).
- QR Droid (version 6.6)
In general, QR Droid’s default scanning engine (“Zapper”), seemed to be able to scan the generated QR codes faster than QR Scanner; however, above QR Version 20, the Zapper engine seemed to be unable to capture data, and I had to switch over to the alternate “ZXing” engine that isn’t quite as fast.
For future: Want to test on bare console with cartridge, but need to figure out how to build one.
If a F18A is detected when the program starts, the “text editor” will start in 80 column mode. Otherwise, the editor starts in 40 column mode. In 40 column mode, total user input possible is 40 columns * 22 rows = 880 characters, which is well under the maximum 1,663 possible characters. In 80 column mode, total input possible is 80 columns * 22 rows = 1760 characters. In that case, only the first 1663 characters will be used and the remaining will be truncated.
There is only one “page”, so while it is a full screen editor, it does not allow the user to scroll.
Commands available in the full screen editor:
Function-S - Left
Function-D - Right
Function-E - Up
Function-X - Down
Function-6 - Proceed – Draw a QR code for the entered text
Function-9 - Draw Demo QR Code (Fest West 2016 note)
Function-0 - Draw Stress-Test QR Code (part, Declaration of Independence)
Fn-9 info: QR Version 12 (65x65 pixels) with original input of 183 bytes
After error correction, total output is 466 bytes (3,728 pixels)
Fn-0 info: QR Version 40 (177x177) with original input of 1,639 bytes
After error correction, output is 3,706 bytes (29,648 pixels)
Future versions may potentially remove the Function-9 and -0 to save space.
For future: I understand there is an undocumented 2-color only bitmap mode called (“Bitmap text mode”, aka “the mode that TI forgot to tell us about”) that could be useful to get more available VDP RAM since it doesn’t use a color table, nor use extra space for sprite tables, etc. I’m not sure if emulators or the F18A support this undocumented mode, though.
I had been doing all my testing on my Android Smartphone, but as I packed up all my gear for Fest West, it occurred to me that I could use a USB handheld laser barcode scanner to read the QR codes as well. Theoretically, if the USB barcode wand is compatible with jedimatt42’s USB keyboard adapter, you could use a future version of my QR Code generator to grab files from one TI an transfer them to another TI “wirelessly”, i.e.,
TI #1 -> generate QR code -> Scan with USB barcode wand -> keyboard input into USB keyboard adapter -> save keystrokes as a file on TI #2.
One problem with this scenario is that I designed the QR code to transmit data as 8-bit bytes, which wouldn’t be mapped to all keyboard characters. Perhaps if the data were mapped to 7-bit BASE64 encoding first.
Intention is to run on Non-Expanded TI (uses only VDP RAM and scratchpad RAM), and it had been working earlier this week, but some of the other changes I made later on seemed to break it running on a non-32K console. Need to investigate.
There’s probably lots of room for improvement in terms of performance. Portions of the code I was trying to code to be as performant as possible, and for other portions, my brain was sufficiently fried to the point that I just wanted to make the code work and I threw performance out the window to just “get it done”.
The code seems mostly bug-free, though I have occasionally noticed rendering errors. If you do happen to see an invalid QR code rendered, please send me a screenshot. I’ve addressed each repeatable bug I’ve found. Non-reproducible bugs have been harder to address.
I adapted snippets assembly source code I found on the Internet from various sources. Acknowledgments:
- Matthew Hagerty’s public domain “Yin/Yang” code from March 2006 served as an awesome “tutorial” for using bitmap graphics. I used some of his VDP routines.
- Matthew Hagerty’s F18A unlock/detection code from March 2012.
- TurboForth’s GPLLNK routine, that TurboForth adapted from the July 1986 edition of “Smart Programmer”. I needed this routine to grab the character set from GPL to load for the 40- and 80- column modes.
- TurboForth’s lowercase character font set.
- Tim Tesch’s public domain KSCAN routine from S&T Software’s Backup-Bit Remover v1.0.
I’m releasing a RPK fie and DSK file. I have tested both with Js99er.net. The DSK file contains a program called “DEMO” that is an EA5 image.
I will release the source code under the MIT License once I clean up the comments.