• Please review our updated Terms and Rules here

Expanding the WY-60 font ROM

JohnElliott

Veteran Member
Joined
Sep 1, 2006
Messages
823
Location
Sussex, UK
The WY-60 terminal ROMs have been dumped and are at Bitsavers: http://www.bitsavers.org/pdf/wyse/WY-60/firmware/

Looking at the files, the screen font is to be found in 202008-03_8051.bin. However it's stored in a compressed format that makes it less than straightforward to dump.
How it works is:
The font starts at offset 0xE7 in the ROM. Each character starts with four bytes. The first two are a big-endian word describing the 16-line bitmap, the second a big-endian word describing the 8-line bitmap.
For the 16-line bitmap, if a bit is set in its description word (starting with the topmost bit) then the next byte is read from the ROM and added to the character bitmap. If it is clear then the last byte is repeated and added to the character bitmap.
For the 9-line bitmap, if bit 0 is set the same method is followed, using the high 9 bits of the word. If bit 0 is clear, then the bytes come from the 16-character bitmap, the source lines indicated by which bits are set in the word.

Here's some C that expands the font bitmaps to readable text:
C:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

unsigned char rom1[4096];

unsigned char chbuf16[16], chbuf9[16];


void prbyte(FILE *fp, unsigned char c)
{
    unsigned char mask;
    int n;

    for (n = 0, mask = 0x80; n < 8; n++)
    {
        fputc((c & mask) ? '#' : '-', fp);
        mask = mask >> 1;
    }
}


/* Expand a ROM character bitmap */
size_t expchar(int addr)
{
    int a1, a2;
    unsigned short mask;
    size_t pos, result;
    unsigned short m1 = rom1[addr    ] * 256 + rom1[addr + 1];
    unsigned short m2 = rom1[addr + 2] * 256 + rom1[addr + 3];
    unsigned char last;

    memset(chbuf16, 0, sizeof(chbuf16));
    memset(chbuf9, 0, sizeof(chbuf9));
    for (last = 0, pos = 0, a1 = addr + 4, mask = 0x8000; pos < 16; pos++)
    {
        if (m1 & mask)
        {
            last = rom1[a1++];
        }
        mask = mask >> 1;
        chbuf16[pos] = last;
    }
    if (m2 & 1)
    {
        for (last = 0, pos = 0, mask = 0x8000; pos < 9; pos++)
        {
            if (m2 & mask)
            {
                last = rom1[a1++];
            }
            mask = mask >> 1;
            chbuf9[pos] = last;
        }
    }
    else
    {
        for (last = 0, a2 = 0, pos = 0, mask = 0x8000; pos < 16; pos++)
        {
            if (m2 & mask)
            {
                chbuf9[a2++] = chbuf16[pos];
            }
            mask = mask >> 1;
        }
    }

    result = a1 - addr;

    return result;
}


int main(int argc, char **argv)
{
    FILE *fp;
    int n;
    int l;
    int nc, y;

     fp = fopen("202008-03_8051.bin", "rb");
    if (!fp)
    {
        perror("202008-03_8051.bin");
        return 1;
    }
    fread(rom1, 1, sizeof(rom1), fp);
    fclose(fp);

    fp = fopen("wyse16.txt", "w");
    if (!fp)
    {
        perror("wyse16.txt");
        return 1;
    }
    fprintf(fp, "%%PSF2\nVersion: 0\nFlags: 0\nLength: 278\n"
            "Width: 8\nHeight: 16\n");

    for (nc = 0, n = 0xE7; n < 0x1000; )
    {
        l = expchar(n);

        fprintf(fp, "%%\n");
        fprintf(fp, "// %04x: Character %d\nBitmap: ", n, nc++);
        for (y = 0; y < 16; y++)
        {
            prbyte(fp, chbuf16[y]);
            if (y < 15) fprintf(fp, " \\\n\t");
            else fputc('\n', fp);
        }
        n += l;
    }
    fclose(fp);
    fp = fopen("wyse9.txt", "w");
    if (!fp)
    {
        perror("wyse9.txt");
        return 1;
    }

    fprintf(fp, "%%PSF2\nVersion: 0\nFlags: 0\nLength: 278\n"
            "Width: 8\nHeight: 9\n");
    for (nc = 0, n = 0xE7; n < 0x1000; )
    {
        l = expchar(n);

        fprintf(fp, "%%\n");
        fprintf(fp, "// %04x: Character %d\nBitmap: ", n, nc++);
        for (y = 0; y < 9; y++)
        {
            prbyte(fp, chbuf9[y]);
            if (y < 8) fprintf(fp, " \\\n\t");
            else fputc('\n', fp);
        }
        n += l;
    }
    fclose(fp);
    return 0;
}
 

Attachments

  • wyse9.png
    wyse9.png
    1.4 KB · Views: 17
  • wyse16.png
    wyse16.png
    1.9 KB · Views: 19
Last edited:
I am currently working to recreate the WY-60 character sets, first as actual bit map glyphs with the WY-60 encoding (0 to 7F, basically the 7-bit ASCII half of ISO8859-1). I've been doing some reading in the Programmer's Guide and the terminal's display of its character cell fonts is quite interesting.

For the larger font, (26-line, 80-column format) the guide describes each character as a 7x12 matrix in a 10x16 cell. Although really, you can use the full height of the cell, so it's more like a 7x16 matrix in a 10x16 cell. So why is each character generally 7 dots wide? According to the guide, when dots are in the eighth column of the cell (which the guide calls "column 0"), they are extended rightwards to the remaining two columns. Apparently, this is how the box-drawing graphics symbols are able to connect to each other, when logically, they are only 8 dots wide, but in a 10-dot-wide cell.

I guess the same principle applies to the smaller font, which is limited to a 5x9 matrix in a 7x9 cell.

Just as a final note, thanks for dumping the fonts from the ROMs. It has helped immensely in my research, especially since some of the character bit maps in the Programmer's Guide are actually incorrect when compared to the ROM dump.
 
Back
Top