Previous Thread
Next Thread
Print Thread
Page 65 of 80 1 2 63 64 65 66 67 79 80
Joined: Feb 2014
Posts: 1,124
Likes: 193
G
Very Senior Member
Offline
Very Senior Member
G
Joined: Feb 2014
Posts: 1,124
Likes: 193
I was reading the manual for the Fingerprint G+ card and it seemed really similar to the Grappler+ manual.

Fingerprint G+ card manual / Grappler + manual:

[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com][Linked Image from i.imgur.com]

Joined: Mar 2001
Posts: 17,234
Likes: 260
R
Very Senior Member
Offline
Very Senior Member
R
Joined: Mar 2001
Posts: 17,234
Likes: 260
A lot of cards back then were designed and documented by independent engineering firms for whoever did the manufacturing (much like how a lot of video cards today use the Nvidia or AMD reference design), and they likely would keep them pretty similar across customers. That's a good catch though!

Joined: Feb 2014
Posts: 1,124
Likes: 193
G
Very Senior Member
Offline
Very Senior Member
G
Joined: Feb 2014
Posts: 1,124
Likes: 193
I was able to get the fingerprint g+ to print something in color. The fingerprint g+ supports the epson jx-80.

[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]

it also supports printing the lo-res screen:

[Linked Image from i.imgur.com]

Joined: Feb 2014
Posts: 1,124
Likes: 193
G
Very Senior Member
Offline
Very Senior Member
G
Joined: Feb 2014
Posts: 1,124
Likes: 193
The fingerprint g+ has a 16k rom which has an interesting banking scheme:

To appear in the 2k window at C800-CFFF the 16K rom has 8 2k banks.

Writes to C088,x will set the bank.

The first bit of code at C800 and C100 will reset the bank to 0 so it will always start with bank 0 no matter which bank is initially selected.

Code
c800: 48        pha
c801: a9 00     lda #$00
c803: 99 88 c0  sta $c088, y
and this code gets repeated at the beginning of every bank.

What's cool is that the bank number of the current bank is at CFFC. So if we want to execute some code in another bank and come back to our current bank, we just read CFFC, store it somewhere, then write that value back to C088,y.

Code
0000-07ff is bank 00
0800-0fff is bank 80
1000-17ff is bank 40
1800-1fff is bank c0
2000-27ff is bank 20
2800-2fff is bank a0
3000-37ff is bank 60
3800-3fff is bank e0

reading from cffc will tell you the current bank:

hexdump fingerprint_gplus_27c128.u1 | grep "000.[7f]f0"

00007f0 c080 eaea 80ad 9903 c088 ff60 ff00 0fff    <=== bank = 00
0000ff0 c080 eaea 80ad 9903 c088 ff60 ff80 0fff    <=== bank = 80
00017f0 c080 eaea 80ad 9903 c088 ff60 ff40 0fff    <=== bank = 40
0001ff0 c080 eaea 80ad 9903 c088 ff60 ffc0 0fff
00027f0 c080 eaea 80ad 9903 c088 ff60 ff20 0fff
0002ff0 c080 eaea 80ad 9903 c088 ff60 ffa0 0fff
00037f0 c080 eaea 80ad 9903 c088 ff60 ff60 0fff
0003ff0 c080 eaea 80ad 9903 c088 ff60 ffe0 0fff    

bit 7 is +800         8
bit 6 is +1000        4
bit 5 is +2000        2        

Code

ROM_START(fingerprint_gplus_rom)
	ROM_REGION(0x4000, "prom", 0)
	ROM_LOAD( "fingerprint_gplus_27c128.u1", 0x0000, 0x4000, CRC(90bdec85) SHA1(7218016ad00b2d65a3ff473b6950d1e6e047f717) )
ROM_END


void a2bus_fingerprint_gplus_device::write_c0nx(u8 offset, u8 data)
{

	switch (offset)
	{
...		
	case 8U:
		bank_base_address = (data & 0x80 ? 0x800 : 0) + (data & 0x40 ? 0x1000 : 0) + (data & 0x20 ? 0x2000 : 0);
		printf("bank base address = %x\n",bank_base_address);
	}
}

uint8_t a2bus_fingerprint_gplus_device::read_c800(uint16_t offset)
{
	return m_prom[offset + bank_base_address];
}


and the code for c100 is at offset 3000 + 100 * slot number.


Code
d71c: a2 c7     ldx #$c7      c7 is slot address
d71e: a0 70     ldy #$70     70 is slot offset
d720: 84 26     sty $26
d722: 8e f8 07  stx $07f8
d725: a9 00     lda #$00
d727: 8d ff cf  sta $cfff
d72a: 99 88 c0  sta $c088, y    reset the bank to zero


Code
f = io.open("fingerprint_gplus_27c128.u1")  a=f:read("*a") print(a:len()) for i=0,a:len()-1 do c = a:byte(i+1) if (i%64 == 0) then print() io.write(string.format("%4x",i)..": ") end c = c % 128 if c>=32 and c<=126 then io.write(string.char(c)) else io.write(".") end if c==0x1b then io.write("ESC") end end print()

for j=0,6 do o0=0x3100 o1=0x3100 + j*0x100 for i=0,255 do if a:byte(i+1+o0) ~= a:byte(i+1+o1) then print(i,string.format("%x",i+o1),string.format("%x",a:byte(i+1+o0)),string.format("%x",a:byte(i+1+o1))) end end end
29	321d	c1	c2
31	321f	10	20
29	331d	c1	c3
31	331f	10	30
29	341d	c1	c4
31	341f	10	40
29	351d	c1	c5
31	351f	10	50
29	361d	c1	c6
31	361f	10	60
29	371d	c1	c7

this same pattern gets repeated at offset 3900

Code
> for j=0,6 do o0=0x3900 o1=0x3900 + j*0x100 for i=0,255 do if a:byte(i+1+o0) ~= a:byte(i+1+o1) then print(i,string.format("%x",i+o1),string.format("%x",a:byte(i+1+o0)),string.format("%x",a:byte(i+1+o1))) end end end
29	3a1d	c1	c2
31	3a1f	10	20
29	3b1d	c1	c3
31	3b1f	10	30
29	3c1d	c1	c4
31	3c1f	10	40
29	3d1d	c1	c5
31	3d1f	10	50
29	3e1d	c1	c6
31	3e1f	10	60
29	3f1d	c1	c7
31	3f1f	10	70

comparing the two banks shows a few differences.

Code
> for j=0,6 do o0=0x3100 o1=0x3900 + j*0x100 for i=0,255 do if a:byte(i+1+o0) ~= a:byte(i+1+o1) then print(i,string.format("%x",i+o1),string.format("%x",a:byte(i+1+o0)),string.format("%x",a:byte(i+1+o1))) end end end
129	3981	fe	27
131	3983	fe	0
193	39c1	fe	27
195	39c3	fe	0
29	3a1d	c1	c2
31	3a1f	10	20
129	3a81	fe	27
131	3a83	fe	0
193	3ac1	fe	27
195	3ac3	fe	0
29	3b1d	c1	c3
31	3b1f	10	30
129	3b81	fe	27
131	3b83	fe	0
193	3bc1	fe	27
195	3bc3	fe	0

It seemed to work fine mapping offset 3000 + 100 * slotno() into C100

Code
u8 a2bus_fingerprint_gplus_device::read_cnxx(u8 offset)
{
	return m_prom[offset+0x3000+0x100*slotno()];
}

and I think it's very similar to the grappler plus with regards to reading c080 for status, writing c080 for outputting data to the printer.

it writes c088 to change the bank.

it reads c08f to read the DIP switches on the card. Only switches 1-6 are used, 7-8 are unused.
and it's the inverted bit pattern from the manual so 1 will be zero and 0 will be 1.
SW6 = b0, SW5 = b1, SW4 = b2, SW3 = b3, SW2 = b4, SW1 = b5

Joined: Feb 2014
Posts: 1,124
Likes: 193
G
Very Senior Member
Offline
Very Senior Member
G
Joined: Feb 2014
Posts: 1,124
Likes: 193
So the fingerprint g+ is supposed to support regular hi-res:

[Linked Image from i.imgur.com]

which looks fine.

It's also supposed to support double hi-res and lo-res, however color 15 white prints as black for some reason.

[Linked Image from i.imgur.com]
(doing some experiments changing the cf4b table while it's printing)

There's a table at cf4b that seems to control the printed colors. There's a 2 color dither, offset 0-15 low nibble is color a and 16-31 low nibble is color b.
It's actually quite clever, bit 3 is black, bit 2 is magenta, bit 1 is cyan, bit 0 is yellow.


So if I take entries 15 and 31 for color 15 = white

[Linked Image from i.imgur.com]

and change them from 8F 8F to 0 and 0

[Linked Image from i.imgur.com]

then the print looks normal:

[Linked Image from i.imgur.com]

[Linked Image from i.imgur.com]

It looks even better if I do some color correction in gimp to more closely match the screen colors:

[Linked Image from i.imgur.com]

Joined: Feb 2014
Posts: 1,124
Likes: 193
G
Very Senior Member
Offline
Very Senior Member
G
Joined: Feb 2014
Posts: 1,124
Likes: 193
Since I've been studying a2 printer cards, I came across this article about a guy who decided to make his own printer card, it's a fun read:

Quote
My tipping point came the day I decided to add a printer. I saved up $1,000 and headed down to the local Apple store in Santa Barbara to buy a Paper Tiger dot matrix printer along with the add-on board to connect it to the computer.

Damn. They wanted $185 for that stupid little board; nearly one quarter of the price of the printer itself. And believe me, I had spent enough time at Radio Shack to know there wasn’t much more than a few dollars worth of parts on it.

It was right then I decided I’d design and sell a competing card.


https://medium.com/predict/going-toe-to-toe-with-steve-jobs-a5a2ed686ab5

Joined: Feb 2021
Posts: 30
T
Member
Offline
Member
T
Joined: Feb 2021
Posts: 30
Wow! I enjoy to read that topics since I am new to this MAME forum. I am now learning a lot about MAME. You are able getting Epson LX (or AP2000) printer emulators working. Are you plan to implement more printer emulators like Gemini 10/10X, older Epson MX/FX (running in 8048 microcontroller) with Graftax-80 (designed for TRS-80 computers) and plotters like ALPS DPG1302 plotter? I love to see printouts in color (Epson JX-80 emulator) but I can't find JX80 in MAME emulator list.

Joined: Jun 2001
Posts: 526
Likes: 37
O
Senior Member
Offline
Senior Member
O
Joined: Jun 2001
Posts: 526
Likes: 37
The #1 question is always "are dumps of every rom, including internal, present in the device available?". If no, then no. If yes, then problably.

Joined: Feb 2004
Posts: 2,603
Likes: 307
Very Senior Member
Offline
Very Senior Member
Joined: Feb 2004
Posts: 2,603
Likes: 307
I’ve added the Orange Micro Buffered Grappler+. It’s kind of like a Grappler+ and Bufferboard combined, but there are some differences. Firstly, it has no host interrupt output, so the C0nX write addresses for interrupt enable/disable aren’t implemented, and bit 7 of C0nX read returns the state of SW1-1 (forced 7-bit mode). Secondly, forced 7-bit mode isn’t implemented by pulling a data line low with the DIP switch, the ROM driver checks the switch value and clears the bit in software if necessary.

However, the microcontroller dump is bad. With 16K buffer RAM (four 6164 chips installed), it doesn’t work. The byte at 0x179 is 0xff (mov a,r7) when it should be 0xfd (mov a,r5). There could be other bad bits in the ROM as well, I don’t think there’s a way to test it.

Joined: Feb 2014
Posts: 1,124
Likes: 193
G
Very Senior Member
Offline
Very Senior Member
G
Joined: Feb 2014
Posts: 1,124
Likes: 193
Hi Vas,

Your buffered grappler driver is really nice and elegant. I could never do that in a million years 8-) Tribute!

I wanted to see the self test for fun so I added a little bit of code to simulate the reset line controlled by an ioport and discovered another corrupt byte:

This is surely incorrect, but it seems to work ok.


Code
INPUT_PORTS_START(bufgrapplerplus)
        PORT_INCLUDE(grapplerplus)

        PORT_START("CNF")
        PORT_CONFNAME(0xff, 0x00, "RAM Size")
        PORT_CONFSETTING(   0xfc, "16K (2 chips)")
        PORT_CONFSETTING(   0xf0, "32K (4 chips)")
        PORT_CONFSETTING(   0x00, "64K (8 chips)")

        PORT_START("Reset")
        PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Reset") PORT_CODE(KEYCODE_DEL_PAD)
INPUT_PORTS_END



added this in device_add_mconfig:

 m_mcu->p2_in_cb().set(FUNC(a2bus_buf_grapplerplus_device::mcu_p2_r));



u8 a2bus_buf_grapplerplus_device::mcu_p2_r()
{
int   retval = (m_mcu_p2 & 0x7f) | 0x4 |  ((machine().time().as_double() < (2.0/60)) ? 0x0 : (ioport("Reset")->read() ? 0x80 : 0x0));    // bit 2 is always 1 since +5 I think

        printf("retval = %x     time=%f\n",retval,machine().time().as_double());

        return retval;

}


If you want to see the self test every time, make the above test ((machine().time().as_double() < 3.0)


since the input system gets updated every frame it won't see the key down until .0168 of time (1/60th second) so that's why I've got the 2.0/60 in the test

retval = ee time=0.000298
retval = ee time=0.001224
...
retval = ee time=0.013711
retval = ee time=0.015272
retval = 6e time=0.016833 <<< input system picks up key down after 1 frame and ee --> 6e
retval = 6e time=0.017728


Code
0:330: 0a     in   a,p2     get value of p2
0:331: f2 47  jb7  $347      bit 7 = reset    'reset active low so jump to 347 and set the flag if reset isn't pressed
0:333: ff     mov  a,r7     -- I think r6 and r5 are a "countdown timer"        <<<<< this should be  fe instead of ff  mov a,r6 since the jnz responds to the accumulator only
0:334: ce     dec  r6
0:335: 96 38  jnz  $338     test if r6 is nonzero
0:337: cd     dec  r5
0:338: fd     mov  a,r5
0:339: 4e     orl  a,r6
0:33a: 96 00  jnz  $300    if r5/r6 are nonzero then jump to refresh ram
0:33c: 0a     in   a,p2   (once we get here, we keep spinning until the reset button is released)
0:33d: f2 41  jb7  $341
0:33f: 64 3c  jmp  $33C      -- spin again
0:341: 76 4f  jf1  $34F   -- flag1 set, jump to 34f
0:343: c5     sel  rb0
0:344: 34 8e  call $18E     self test
0:346: d5     sel  rb1
0:347: a5     clr  f1
0:348: b5     cpl  f1                   set f1

64k:

[Linked Image from i.imgur.com]

32k:
[Linked Image from i.imgur.com]
16k:
[Linked Image from i.imgur.com]

Sorry about the bad dump, I tried to get a good dump. I dumped it 3 times and they were all identical.


Some fun testing with Zoom Grafix: taking the printer offline and printing 2 x 3 will go completely in the buffer.

3x3 will get most of the way down before it has to wait. If you set the left margin to zero you almost get to the bottom.

(3*280+6) * (3*192/7) = 69614 bytes so a little bigger than 64k.

Start 3x3 printout:
[Linked Image from i.imgur.com]

Buffer full, has to wait about 3/4 way down:
[Linked Image from i.imgur.com]

Page 65 of 80 1 2 63 64 65 66 67 79 80

Link Copied to Clipboard
Who's Online Now
3 members (yugffuts, shattered, 1 invisible), 229 guests, and 0 robots.
Key: Admin, Global Mod, Mod
ShoutChat
Comment Guidelines: Do post respectful and insightful comments. Don't flame, hate, spam.
Forum Statistics
Forums9
Topics9,328
Posts122,128
Members5,074
Most Online1,283
Dec 21st, 2022
Our Sponsor
These forums are sponsored by Superior Solitaire, an ad-free card game collection for macOS and iOS. Download it today!

Superior Solitaire
Forum hosted by www.retrogamesformac.com