Previous Thread
Next Thread
Print Thread
Page 67 of 78 1 2 65 66 67 68 69 77 78
Joined: Feb 2004
Posts: 2,291
Likes: 19
Very Senior Member
Online Content
Very Senior Member
Joined: Feb 2004
Posts: 2,291
Likes: 19
Originally Posted by Golden Child
Ok I thought I'd try to redump the 8048 on the Buffered Grappler+, and did it around 10 times and kept getting the exact same results.

Therefore, something must be wrong. Since it's powered by a USB cable, I dug around and found a different usb power supply and guess what - the read is slightly different.
If you got a different dump with one thing, maybe you should use a better power supply and re-dump everything you dumped with that setup and see if any other things have bad bits.

Joined: Feb 2014
Posts: 681
Likes: 9
G
Senior Member
Offline
Senior Member
G
Joined: Feb 2014
Posts: 681
Likes: 9
Original Grappler schematic:

https://archive.org/details/manualsonline-id-6b56a0aa-4089-4658-a2c6-de559ed3a773/page/n17/mode/2up

The ProGrappler manual doesn't have schematics unfortunately.

https://archive.org/details/ProGrappler/mode/2up

I was doing a little bit of circuit tracing on the ProGrappler and two of the data lines are swapped I think. I'll have to check because I can't remember exactly.

According to my notes:

"I was looking at the prograppler dump and it looked really horrible, so I thought I'd do some checking on the board with a multimeter,
looks like they did a little bit of "protection" where they swapped d3/d4 and a2/a3 and a6/a7."

Joined: Feb 2014
Posts: 681
Likes: 9
G
Senior Member
Offline
Senior Member
G
Joined: Feb 2014
Posts: 681
Likes: 9
Hi Vas,

The dumper in question is a Willem LPT 6.0 which I got specifically to dump the 8048. Pretty much everything else I've been doing has been with a TL866 II Plus. With the Willem the 8048 needs some different voltages and uses a special adapter. So it's really just this one dump and it exposed the bad power supply issue.

Joined: Feb 2004
Posts: 2,291
Likes: 19
Very Senior Member
Online Content
Very Senior Member
Joined: Feb 2004
Posts: 2,291
Likes: 19

Interesting, this one doesn’t automatically generate strobe pulses, doesn’t use Apple’s trick of flipping a ROM address line while waiting for the printer to acknowledge a character, doesn’t generate interrupts, and doesn’t have DIP switches. Looks like a very simple card.

Originally Posted by Golden Child
The ProGrappler manual doesn't have schematics unfortunately.

https://archive.org/details/ProGrappler/mode/2up

I was doing a little bit of circuit tracing on the ProGrappler and two of the data lines are swapped I think. I'll have to check because I can't remember exactly.

According to my notes:

"I was looking at the prograppler dump and it looked really horrible, so I thought I'd do some checking on the board with a multimeter,
looks like they did a little bit of "protection" where they swapped d3/d4 and a2/a3 and a6/a7."

Yeah, looks like by this time they were trying to make it harder for people to clone the card. This one probably requires more reverse-engineering to emulate.

Joined: Feb 2014
Posts: 681
Likes: 9
G
Senior Member
Offline
Senior Member
G
Joined: Feb 2014
Posts: 681
Likes: 9
I think the Grappler and the "Orange Interface" are actually the same card but with different roms. The Grappler adds graphic dump capability (but only single printer specific, like Epson). The schematic in the Grappler manual says "Orange Interface".

I can try to trace out the connections on the Pro Grappler but I'm *really* slow at it with my multimeter.

Joined: Feb 2004
Posts: 2,291
Likes: 19
Very Senior Member
Online Content
Very Senior Member
Joined: Feb 2004
Posts: 2,291
Likes: 19
I added the Grappler (without the +). It occasionally drops a character. With logging turned on, you can see that it really doesn’t wait for the previous character to be acknowledged before outputting another character in these cases. It isn’t a “time travel” effect where it doesn’t have time to see the acknowledge latch being cleared. I don’t have the energy to debug it further, but it could be another bad dump, or an original bug.

Joined: Feb 2014
Posts: 681
Likes: 9
G
Senior Member
Offline
Senior Member
G
Joined: Feb 2014
Posts: 681
Likes: 9
Hmmmm. It all looks very reasonable,

Code
./unidasm -arch m6502  -basepc 0xc800 grappler_2716_U6_eps_1c1982.bin | grep c08 -A 6 -B 5
cbcb: b9 81 c0  lda $c081, y
cbce: 29 04     and #$04
cbd0: ea        nop                       // guess they don't care about paper out
cbd1: ea        nop
cbd2: b9 81 c0  lda $c081, y
cbd5: 29 02     and #$02           //  printer not selected
cbd7: f0 46     beq $cc1f
cbd9: b9 81 c0  lda $c081, y
cbdc: 29 08     and #$08         //  loop here if busy
cbde: d0 f9     bne $cbd9
cbe0: bd 38 07  lda $0738, x
cbe3: 29 08     and #$08
cbe5: f0 04     beq $cbeb

Just running one CTRL+I G will start printing garbage.

Does the ap2000 have to synchronize itself just as the grappler is synchronizing?

It seems that the grappler is doing all the synchronizing, and the ap2000 and its e05a30 device doesn't have to synchronize.
Code
machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grappler_device::set_strobe), this), 0);

Joined: Feb 2014
Posts: 681
Likes: 9
G
Senior Member
Offline
Senior Member
G
Joined: Feb 2014
Posts: 681
Likes: 9
Just as an experiment to see if it's synchronization issues I put

config.set_maximum_quantum(attotime::from_usec(15)); into device_add_mconfig and it seemed to help.



One other thing I noted was that reads to C0nx have side effects, so maybe a debugger guard would be good here (for completeness):

Interesting that they didn't worry about the R/W line for access to C082 and C084 so reads can set/clear the strobe line as well as writes.

Code
u8 a2bus_grappler_device::read_c0nx(u8 offset)
{
        LOG("Read C0n%01X\n", offset);

        if (BIT(offset, 1)) // A1 - assert strobe
                machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grappler_device::set_strobe), this), 0);
        else if (BIT(offset, 2)) // A2 - release strobe
                machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grappler_device::set_strobe), this), 1);


Joined: Feb 2004
Posts: 2,291
Likes: 19
Very Senior Member
Online Content
Very Senior Member
Joined: Feb 2004
Posts: 2,291
Likes: 19
Here’s a log of it missing a character:
Code
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Write C0n1=20
[:sl1:grappler] Output data 20
[:sl1:grappler] Read C0n2
[:sl1:grappler] Write C0n2=20
[:sl1:grappler] Output /STROBE=0
[:sl1:grappler] Clearing acknowledge latch
[:sl1:grappler] BUSY=1
[:sl1:grappler] Output /STROBE=0
[:sl1:grappler] BUSY=0
[:sl1:grappler] Read C0n4
[:sl1:grappler] Write C0n4=20
[:sl1:grappler] Output /STROBE=1
[:sl1:grappler] Output /STROBE=1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Write C0n1=20
[:sl1:grappler] Output data 20
[:sl1:grappler] Read C0n2
[:sl1:grappler] Write C0n2=20
[:sl1:grappler] Output /STROBE=0
[:sl1:grappler] Previous data not acknowledged
[:sl1:grappler] Output /STROBE=0
[:sl1:grappler] Read C0n4
[:sl1:grappler] Write C0n4=20
[:sl1:grappler] Output /STROBE=1
[:sl1:grappler] Output /STROBE=1
[:sl1:grappler] /ACK=0
[:sl1:grappler] Set acknowledge latch
[:sl1:grappler] BUSY=1
[:sl1:grappler] BUSY=0
[:sl1:grappler] /ACK=1
It writes C0n2 to assert /STROBE, and the acknowledge latch is cleared in a callback from the scheduler. There are no intervening reads of C0n1 where it could mistakenly still see the acknowledge latch still set from the previous byte (this could happen if the timeslice wasn’t aborted fast enough). It doesn’t wait for the acknowledge latch to be set before sending the next byte. The acknowledge after the second byte comes very quickly because it’s actually the acknowledge for the first byte, and the second byte is lost.

Now look at a more normal pair of bytes:
Code
[:sl1:grappler] Write C0n1=20
[:sl1:grappler] Output data 20
[:sl1:grappler] Read C0n2
[:sl1:grappler] Write C0n2=20
[:sl1:grappler] Output /STROBE=0
[:sl1:grappler] Clearing acknowledge latch
[:sl1:grappler] BUSY=1
[:sl1:grappler] Output /STROBE=0
[:sl1:grappler] Read C0n4
[:sl1:grappler] Write C0n4=20
[:sl1:grappler] Output /STROBE=1
[:sl1:grappler] Output /STROBE=1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] /ACK=0
[:sl1:grappler] Set acknowledge latch
[:sl1:grappler] BUSY=0
[:sl1:grappler] /ACK=1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Write C0n1=20
[:sl1:grappler] Output data 20
[:sl1:grappler] Read C0n2
[:sl1:grappler] Write C0n2=20
[:sl1:grappler] Output /STROBE=0
[:sl1:grappler] Clearing acknowledge latch
[:sl1:grappler] BUSY=1
[:sl1:grappler] Output /STROBE=0
[:sl1:grappler] Read C0n4
[:sl1:grappler] Write C0n4=20
[:sl1:grappler] Output /STROBE=1
[:sl1:grappler] Output /STROBE=1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] Read C0n1
[:sl1:grappler] /ACK=0
[:sl1:grappler] Set acknowledge latch
[:sl1:grappler] BUSY=0
[:sl1:grappler] /ACK=1
See how it sits in a polling loop waiting for the acknowledge latch to be set before it continues with the next byte?

Joined: Feb 2004
Posts: 2,291
Likes: 19
Very Senior Member
Online Content
Very Senior Member
Joined: Feb 2004
Posts: 2,291
Likes: 19
OK, I probably just suck at 6502, but what is the purpose of tay immediately followed by tya?
Code
 C940  lda #$87                                            A9 87
 C942  jsr $cbc0                                           20 C0 CB
 C945  tay                                                 A8
 C946  tya                                                 98
 C947  cmp #$8d                                            C9 8D
 C949  bne $c968                                           D0 1D
 C94B  lda #$00                                            A9 00
 C94D  sta $0438, x                                        9D 38 04

Page 67 of 78 1 2 65 66 67 68 69 77 78

Link Copied to Clipboard
Who's Online Now
0 members (), 20 guests, and 6 robots.
Key: Admin, Global Mod, Mod
ShoutChat
Comment Guidelines: Do post respectful and insightful comments. Don't flame, hate, spam.
Forum Statistics
Forums9
Topics8,993
Posts118,151
Members5,005
Most Online890
Jan 17th, 2020
Forum Host
These forums are hosted by www.retrogamesformac.com
Forum hosted by www.retrogamesformac.com