Firmware Update Display
Firmware Update Display State Machine
During firmware updates, the KN5000 displays status messages on the LCD using pre-rendered 1-bit bitmap images stored in the Program ROM. This page documents the complete display state machine, correlating each bitmap with its update stage and the code that triggers it.
Bitmap Messages
All update bitmaps are 224 pixels wide x 22 pixels tall, stored as packed 1bpp data (28 bytes/row x 22 rows = 616 bytes each). They are rendered by Draw_FlashMemUpdate_message_bitmap (0xEF5040), which unpacks each bit to an 8bpp pixel and blits to VRAM via an offscreen buffer at 0x43C00.
| Bitmap | ROM Address | Message Text | Display Parameters |
|---|---|---|---|
Bitmap_1bit_Please_Wait |
0xE00B2E |
“Please Wait !!” | X=48, Y=80, FG=8, BG=3 |
Bitmap_1bit_Flash_Memory_Update |
0xE0018E |
“Flash Memory Update” | X=48, Y=80, FG=8, BG=2 |
Bitmap_1bit_Now_Erasing |
0xE003F6 |
“Now Erasing!!” | X=48, Y=160, FG=8, BG=2 |
Bitmap_1bit_FD_to_Flash_Memory |
0xE0065E |
“FD -> Flash Memory” | X=48, Y=160, FG=8, BG=2 |
Bitmap_1bit_Completed |
0xE008C6 |
“Completed!” | X=48, Y=160, FG=8, BG=1 |
Bitmap_1bit_Turn_On_AGAIN |
0xE01266 |
“Turn On AGAIN !!” | X=48, Y=200, FG=8, BG=1 |
Bitmap_1bit_Change_FD_2_of_2 |
0xE00D96 |
“Change FD (2/2)” | X=48, Y=160, FG=8, BG=2 |
Bitmap_1bit_Illegal_Disk |
0xE00FFE |
“Illegal Disk!” | X=48, Y=160, FG=8, BG=2 |
FG/BG values are palette indices pushed onto the stack before calling the draw routine. BG=1 appears to be used for “final” messages (completion), BG=2 for “in-progress” messages, and BG=3 for the initial boot wait screen.
Rendering: Draw_FlashMemUpdate_message_bitmap
Address: 0xEF5040
Input:
- XWA = pointer to 1bpp bitmap data (24-bit ROM address)
- BC = X start coordinate (left edge)
- DE = Y start coordinate (top edge)
- Stack: foreground color (byte), background color (byte)
Algorithm:
- For each byte in the 616-byte bitmap (28 bytes x 22 rows):
- Divide byte index by 28 to determine the current row
- For each bit in the byte, use a bit mask lookup table (at DRAM address from
0xE34A) - If bit is set: write foreground color to pixel; otherwise: write background color
- Pixel address = offscreen buffer (
0x43C00) + Y*320 + X - After rendering all pixels, blit the entire offscreen buffer to VRAM
The Y*320 multiplication uses the shift-add trick: (Y << 2 + Y) << 6 = Y * 320, matching the 320-pixel LCD width.
Progress Bar
During flash erase operations, Flash_BurnWithProgress (0xEF4709) displays an animated progress bar:
- Initial X position: 50 pixels (0x32)
- Y position: 180 pixels (0xB4)
- Bar height: 5 pixels
- Step size: 8 pixels per increment
- Increment trigger: Every 500 (0x1F4) flash word-program operations
The progress bar grows left-to-right across the screen. The counter at DRAM address 1033 tracks word-program operations; when it exceeds 500, the bar extends by 8 pixels and the counter resets.
The bar is drawn using VRAM_FillRect with parameters (X=IZ, Y=0xB4, width implied, height=5).
State Machine
Entry Conditions
The firmware update is triggered during boot when all three conditions are met:
- Firmware version byte at
0xFFFFE8equals0xFF(update-mode sentinel) - A floppy disc is present (disc change signal on port PD bit 6)
- Button scan returns value 4 (specific key held during boot)
Boot-Time Pre-Update Display
[Power On]
|
v
MainCPU_self_test_routines
|
v
Get_Firmware_Version == 0xFF?
|yes |no
v v
"Please Wait !!" Normal boot
(at Y=80, BG=3) sequence
|
v
[System init, task scheduler, Sub-CPU check]
|
v
Floppy present AND button==4?
|yes |no
v v
FLASH_MEM_UPDATE Normal boot
|
v
[infinite loop at 0xEF05E6 after return]
Main Update Flow (FLASH_MEM_UPDATE at 0xEF4F6F)
FLASH_MEM_UPDATE
|
v
Check floppy present ──no──> Return (no update)
|yes
v
FDC_InitRecalibrate
|
v
Detect_Disk_Type ──> type stored in register pointer 0xFB
|
v
Validate flash hardware (0xEF3D0E)
|
v
Is type == 6 (HDAE5000)? ──yes──> Skip to HDAE5000 path
|no
v
╔══════════════════════════════════╗
║ "Flash Memory Update" ║
║ (at Y=80, BG=2) ║
╚══════════════════════════════════╝
|
v
Erase_and_Burn____when_disk_is_valid(type)
|
v
╔══════════════════════════════════╗
║ "Completed!" ║
║ (at Y=160, BG=1) ║
╠══════════════════════════════════╣
║ "Turn On AGAIN !!" ║
║ (at Y=200, BG=1) ║
╚══════════════════════════════════╝
|
v
[Check for HDAE5000 update too]
|
v
Return → infinite loop
HDAE5000-Specific Path
When the detected disc type is 6 (HDAE5000 extension firmware), the firmware:
- Validates the HDAE5000 flash chip with
Flash_IdentifyAndValidateChip - If flash chip not found → skip (no update)
- Otherwise: displays “Flash Memory Update”, erases and programs, then shows “Completed!” + “Turn On AGAIN!!”
The HDAE5000 path uses Flash_WaitUntilReady before programming and writes uncompressed data directly to flash at 0x280000.
Erase and Burn State Machine
Erase_and_Burn____when_disk_is_valid (0xEF4745) handles all non-HDAE5000 update types:
Erase_and_Burn
|
v
╔══════════════════════════════════╗
║ "Now Erasing!!" ║
║ (at Y=160, BG=2) ║
╚══════════════════════════════════╝
|
v
Validate type (1-8 range)
|invalid |valid
v v
"Illegal Disk!" Jump to type-specific handler
(infinite halt) via offset table at 0xE00178
Per-Type Handler Display Sequences
Each update type has a specific handler that shows different sequences of messages:
Type 7: Program ROM (Compressed)
"Now Erasing!!"
|
v
Erase flash sectors at 0x3E0000 and 0x3F0000
|
v
Flash_BurnWithProgress (with progress bar)
|
v
"FD -> Flash Memory"
|
v
LZ_Decompress_Init + LZSS_Decompress_ToFlash
|
v
Return → "Completed!" + "Turn On AGAIN!!"
Type 8: Table Data ROM (Compressed)
"Now Erasing!!"
|
v
Flash_BurnWithProgress (with progress bar)
|
v
"FD -> Flash Memory"
|
v
LZ_Decompress_Init
|
v
Return → "Completed!" + "Turn On AGAIN!!"
Types 1/3: Program/Table Data (Uncompressed, Disc 1 of 2)
"Now Erasing!!"
|
v
Flash_BurnWithProgress (with progress bar)
|
v
"FD -> Flash Memory"
|
v
FDC_WriteSectors (first half to 0x800000)
|
v
"Change FD (2/2)" ←── wait for disc swap
|
v
[User removes disc 1, inserts disc 2]
|
v
[Wait for disc removal detected]
|
v
[Delay loop: 0x40000 iterations]
|
v
[Wait for new disc insertion detected]
|
v
[Delay loop: 0x200000 iterations]
|
v
Detect_Disk_Type (verify disc 2 matches)
|mismatch |match
v v
Loop back to "FD -> Flash Memory"
"Change FD (2/2)" |
v
FDC_WriteSectors (second half to 0x900000)
|
v
Return → "Completed!" + "Turn On AGAIN!!"
Types 2/4: Program/Table Data (Disc 2 of 2 inserted first)
These are invalid starting discs. If the user inserts disc 2 first, the handler immediately jumps to SHOW_ILLEGAL_DISK_MESSAGE and halts.
Type 5: Custom Data (Compressed)
"Now Erasing!!"
|
v
Flash_WaitUntilReady (target: Custom Data Flash)
|
v
"FD -> Flash Memory"
|
v
FDC_WriteSectors_Compressed (to 0x300000)
|
v
Return → "Completed!" + "Turn On AGAIN!!"
Type 6: HDAE5000 Extension
"Now Erasing!!"
|
v
Flash_WaitUntilReady (target: Extension ROM)
|
v
"FD -> Flash Memory"
|
v
FDC_WriteSectors_Compressed (to 0x280000)
|
v
Return → "Completed!" + "Turn On AGAIN!!"
Error States
Illegal Disk (Fatal)
Displayed when:
- Disc type code is outside range 1-8 (after subtracting 1)
- Types 2 or 4 are used as the starting disc (these are “disc 2 of 2” and cannot start an update)
Address: SHOW_ILLEGAL_DISK_MESSAGE (0xEF482A)
After displaying “Illegal Disk!”, the firmware enters an infinite loop (jr IllegalDisk_HaltLoop at address 0xEF4841). The only recovery is power cycling the keyboard.
Disc Swap Mismatch
When a 2-disc update (types 1/3) prompts for disc 2, it re-runs Detect_Disk_Type after the swap. If the new disc doesn’t match the expected type, the “Change FD (2/2)” message is shown again in a retry loop. This is not a fatal error — the user can try inserting the correct disc.
Flash Hardware Not Found
If Flash_IdentifyAndValidateChip returns 0xFFFF for the HDAE5000 path, the update is silently skipped (no error message). For the main ROM path, if 0xEF3D0E returns 0xFFFFFFFF, the non-HDAE5000 erase/burn is skipped.
LCD Layout During Update
The update messages are positioned vertically on the 320x240 LCD:
Y=0 ┌────────────────────────────────────────┐
│ │
Y=80 │ "Flash Memory Update" (or "Please │
│ Wait !!" during initial boot) │
│ │
Y=160 │ "Now Erasing!!" → "FD -> Flash" │
│ → "Completed!" (messages replace │
│ each other at the same Y position) │
│ │
Y=180 │ ████████████████ (progress bar) │
│ │
Y=200 │ "Turn On AGAIN !!" │
│ │
Y=240 └────────────────────────────────────────┘
Messages at Y=160 are displayed sequentially (each new message overwrites the previous one at the same screen position). The title at Y=80 remains visible throughout.
Code References
| Symbol | Address | Purpose |
|---|---|---|
FLASH_MEM_UPDATE |
0xEF4F6F |
Main entry point |
Draw_FlashMemUpdate_message_bitmap |
0xEF5040 |
1bpp bitmap renderer |
SHOW_FD_TO_FLASH_MEMORY_MESSAGE |
0xEF468E |
Display “FD -> Flash Memory” |
SHOW_ILLEGAL_DISK_MESSAGE |
0xEF482A |
Display “Illegal Disk!” + halt |
SHOW_CHANGE_FLOPPY_2_OF_2_MESSAGE |
0xEF46A8 |
Display “Change FD (2/2)” + wait |
Flash_BurnWithProgress |
0xEF4709 |
Erase with progress bar |
Erase_and_Burn____when_disk_is_valid |
0xEF4745 |
Type dispatcher |
Detect_Disk_Type |
0xEF42FE |
Identify floppy disc type |
We_seem_to_be_running_boot_ROM_code |
0xEF0536 |
Initial “Please Wait” display |
References
- System Update Discs — Disc format, signatures, and file contents
- Flash Programming — Flash erase/program routines and hardware details
- LZSS Compression — SLIDE4K format used by compressed update types
Last updated: March 2026