I think I may have solved the mystery of the missing bottom line. The font data is stored as 8 bits, with the bottom line saved as 3 bytes. These bytes go into a shift register when written to c001,c002 and c003 and they get shifted out at c000.

So now you can see the bottom of the character [:

[Linked Image from i.imgur.com]

so at 2708 DE gets loaded with C001 and C gets 2 so we transfer 3 bytes to c001,c002,c003 with the BLOCK instruction.

then at 2714 we read the value at C000 for our 9th pin, the other 8 bits coming from LDAX (HL+).

[Linked Image from i.imgur.com]


It seems to work for the self test, anyway.




Code

void e05a30_device::write(offs_t offset, uint8_t data)
{
	LOG("%s: e05a30_w([0xC0%02x]): %02x\n", machine().describe_context(), offset, data);

	switch (offset) {
	case 0x0:
	case 0x1:
	case 0x2:
	case 0x3:
		c000_shift_register &= ~(0xff << ((3-offset)*8));
		c000_shift_register |= (data << ((3-offset)*8));
		break;

...

uint8_t e05a30_device::read(offs_t offset)
{
	uint8_t result = 0;

	LOG("%s: e05a30_r([0xC0%02x]): ", machine().describe_context(), offset);

	switch (offset) {
	case 0x0: 
			c000_shift_register <<= 1;  // put shift before the capture
			result = (c000_shift_register & 0x1000000) ? 0x80 : 0x0; 
			break;