Home Page

Ap2000 signs of life

Posted By: Golden Child

Ap2000 signs of life - 07/17/20 08:14 AM

Hi guys,

I thought I'd start a separate thread for this.

There's something strange about how the upd7810 does the analog/digital conversion.

08 is written to the ANM register, which is supposed to do scan mode on inputs AN4 - AN7 and write them to CR0-CR3, but instead of getting the proper value for AN5, 0xFF gets written to CR1.

Code
 
               if (m_adcnt > m_adtot)
                {
                        m_adcnt -= m_adtot;
                        switch (m_adout)
                        {
//                              case 0: CR0 = m_tmpcr ? 0xff:0x00; break;
//                              case 1: CR1 = m_tmpcr ? 0xff:0x00; break;
//                              case 2: CR2 = m_tmpcr ? 0xff:0x00; break;
//                              case 3: CR3 = m_tmpcr ? 0xff:0x00; break;
                                case 0: CR0 = m_tmpcr; break;
                                case 1: CR1 = m_tmpcr; break;
                                case 2: CR2 = m_tmpcr; break;
                                case 3: CR3 = m_tmpcr; break;
                        }
                        m_adin  = (m_adin  + 1) & 0x07;
                        m_adout = (m_adout + 1) & 0x03;
                        if (m_adout == 0)
                                {IRR |= INTFAD;
                                printf(".IRR=%x ",IRR);}

                        m_shdone = 0;


With that mangling above, CR1 gets the expected value, 0xCB.


Code
focus 1
bp 1dee
g

Stopped at breakpoint 1
[MAME]> 

>history 1,10
1DF0: LXI     EA,$0000
1DEE: MOV     A,CR1
1DEB: MVI     EOM,$07
1DE7: SHLD    $C005
1DE3: LHLD    $9925
981A: JMP     $1DE3
001A: JMP     $981A
0019: EXA     
0018: EXX     
2091: RET     
208E: OFFIW   VV:11,$02
208D: RET     
208B: BIT     6,VV:14
2089: BIT     7,VV:11
3162: CALT    ($009A)
3168: JR      $3162
[MAME]> 

>print anm
8
>print a
CB


Before this, I would get 5 beeps which according to the service manual is a voltage error. Now it shows a little bit more life, not working properly yet.

[Linked Image from i.imgur.com]
Posted By: Golden Child

Re: Ap2000 signs of life - 07/17/20 01:04 PM

[Linked Image from i.imgur.com]

I got it to print some data, but it seems to drop characters while it's printing, probably some handshaking problem.

It should print PRINT "DATA TO PRINTER" and have DATA TO PRINTER underneath each line.

But it's a little closer 8-)

The Apple parallel interface sends 8 bit data, and the high bit is set, I just cleared the high bit and the printer liked that data a lot better.
Posted By: Golden Child

Re: Ap2000 signs of life - 07/19/20 01:47 PM

More fiddling around, it seems that the timing for the AD conversion is somehow inconsistent, and setting the conversion delay to a very high value actually makes the online and lf buttons usable.

It also seems that data sent by the Apple parallel interface card doesn't bother to check the acknowledge, it just hits the strobe, so there isn't any flow control.

There's still some characters being dropped by the ap2000, haven't been able to figure that out yet.

I added some blinkenlights to show writes to the portABC and C000-C00F, and it helps to see what's going on. Man, I love blinkenlights.

[Linked Image from i.imgur.com]
Posted By: R. Belmont

Re: Ap2000 signs of life - 07/19/20 08:39 PM

The source for the parallel card's ROM is available; it's possible the ACK isn't hooked up properly.
Posted By: Golden Child

Re: Ap2000 signs of life - 07/20/20 10:01 AM

I looked at the PIC manual, and there's a source code listing for both the ROMs but neither one bothers to look at the ACK, they just seem to write to C0x0 and assume it gets read.

I guess the apple was slow enough that it wasn't a problem but theoretically that could cause dropped characters.

This really surprised me that there's no real flow control as it wouldn't have been hard to add.

[Linked Image from i.imgur.com]

I wrote a little crap BASIC program to write data directly to the parallel card via I/O locations, it's slow enough that it doesn't go too fast for the printer.

Code
  NEW
    1  GOTO 90
    2 POKE PO,C : ? C,PEEK(PI),PEEK(PI)  : RETURN  :   REM PRINT CHAR AND SHOW THE ACK STATUS
    90 C = PEEK(49152+256)   : REM READ FROM C100 TO ACTIVATE AUTOSTROBE
   100 PO = 49152 + 9*16 : PI =  PO+4   : REM C090 FOR OUTPUT C094 FOR ACK INPUT
   105 FOR J = 1 TO 24
   106 C=64+J : GOSUB 2 : Z$=STR$(J) :GOSUB 3000
   110 C = 27:GOSUB 2 : C = ASC("L") : GOSUB 2  : REM ESC L TO ACTIVATE GRAPHICS
   111 C = 127:GOSUB 2
   112 C = 0  : GOSUB 2
   120 FOR I=0 TO 127 : C = I : GOSUB 2 :NEXT
   150 C=13:GOSUB 2:C=10:GOSUB 2
   160 NEXT
   1999 END
   3000 FOR Z = 1 TO LEN(Z$) : C=ASC(MID$(Z$,Z,1)): GOSUB 2 : NEXT : RETURN

RUN


[Linked Image from i.imgur.com]

Another thing that was totaly puzzling me was why the LF wasn't working right, it seemed like I had to hit it twice, and then I noticed that it had PORT_TOGGLE set. Man, that was really baffling to me. I guess it pays to read the code 8-)


Code
        PORT_START("FORMFEED")
        PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Form Feed") PORT_CODE(KEYCODE_7_PAD) //PORT_TOGGLE
        PORT_START("LINEFEED")
        PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Line Feed") PORT_CODE(KEYCODE_9_PAD) //PORT_TOGGLE

Posted By: Golden Child

Re: Ap2000 signs of life - 07/20/20 11:10 AM

I modified the basic program to wait until ACK goes low, printing a dot every time it checks and the high bit is set. It's interesting that when it's printing that the acks doesn't finish right away.

Code
NEW
   1 GOTO 90
   2 POKE PO,C : ? C" ";:X = PEEK(PI) 
   3  IF  X < 128 GOTO 5
   4 ?".";:X=PEEK(PI):GOTO 3
   5 ? : RETURN

    90 C=PEEK(49152+256)   : REM READ FROM C100 TO ACTIVATE AUTOSTROBE
   100 PO = 49152 + 9*16 : PI =  PO+4
   105 FOR J = 1 TO 24
   106 C=64+J : GOSUB 2 : Z$=STR$(J) :GOSUB 3000
   110 C = 27:GOSUB 2 : C = ASC("L") : GOSUB 2
   111 C = 127:GOSUB 2
   112 C = 0  : GOSUB 2
   120 FOR I=0 TO 127 : C = I : GOSUB 2 :NEXT
   150 C=13:GOSUB 2:C=10:GOSUB 2
   160 NEXT
   1999 END
   3000 FOR Z = 1 TO LEN(Z$) : C=ASC(MID$(Z$,Z,1)): GOSUB 2 : NEXT : RETURN

RUN


It sends the 13 and 10 (CR LF)
then ESC L
then num of chars as two bytes

and you can see the dots get very long there, probably very likely to drop chars there if you're not checking the ACK.

[Linked Image from i.imgur.com]
Posted By: Golden Child

Re: Ap2000 signs of life - 07/21/20 03:07 PM

I got really aggravated trying to get it to print graphics because it kept dropping characters. So I thought, why not cheat a little and make a little buffer to hold the data.

And so I finally got some graphics to print. It's still glitching here and there, more to solve, but it was really gratifying to finally see something that looks halfway normal.

Some zoom grafix:

[Linked Image from i.imgur.com]

Trying Triple Dump (some glitching):

[Linked Image from i.imgur.com]
Posted By: R. Belmont

Re: Ap2000 signs of life - 07/21/20 04:04 PM

Interesting. I would assume Triple Dump actually does watch the handshaking, but maybe not.

The card itself apparently does some clever Woz stuff where it changes the PROM address mapping after STROBE is set until ACK comes in. Will need to investigate further.
Posted By: Golden Child

Re: Ap2000 signs of life - 07/21/20 05:58 PM

Yes, it's puzzling because you'd think there would be some kind of flow control.

I saw that my "minibuffer" was getting overrun and that was causing the glitches, so let's boost the size. The buffer has gone from mini to maxi: 8 bytes to 16k and now I said what the heck, 1 meelllion bytes.


Paper Graphics
[Linked Image from i.imgur.com]
Using the 144 vertical dpi (which overprints in multiple passes looks kinda odd) but 72 dpi looks good.

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



Posted By: Golden Child

Re: Ap2000 signs of life - 07/21/20 09:14 PM

Thought I'd give it a spin with PrintMaster on the Amiga.

I tried with the cpc6128 and I was able to start Printmaster using the cpm startup disk with typing "|cpm", but it required a thousand disk swaps and it seemed to have trouble handshaking and dropping characters (even with my buffer). Oddly on the 6128, the arrow keys wouldn't work with Printmaster unless I held down the left arrow key and keeping it pressed, pressed the right arrow key.

As far as I can tell, the Amiga does watch the ack and busy lines and won't send any data while the printer isn't ready.

[Linked Image from i.imgur.com]
Posted By: Golden Child

Re: Ap2000 signs of life - 07/21/20 11:53 PM

Making calendars with Printmaster:

(I wonder how many people in the world are still using Printmaster and Dot Matrix Printers?)

[Linked Image from i.imgur.com]

While fiddling around with the cpc6128 I did encounter a strange bug. For some reason when running with the cpc6128 some of the ap2000's input ports all of a sudden went from active low to active high. This makes the printer boot up into "Data Dump Mode" because it thinks I'm holding down the Line Feed and Form Feed buttons when it starts. It's really weird that the cpc6128's doing that, because the apple2 and the amiga don't have that problem.

I'm doing a subtarget/sources build, could that be causing a problem?
Posted By: Golden Child

Re: Ap2000 signs of life - 07/22/20 03:48 AM

So let's see if the ibm5150 will work with print shop.

Testing the printer gives an error.

[Linked Image from i.imgur.com]

So let's see if we can figure out where it's hanging up.

We'll set an i/o watchpoint with wpi 378,8,r and then when it hits, set al=df (ack is active low) and then printshop will continue.
After doing that we disable the watchpoint.

[Linked Image from i.imgur.com]

This diagram from art of asm shows the status register.

So going into src/devices/machine/pc_lpt.cpp and adding an xor on STATUS_ACK seems to fix the error message.
Code
int8_t pc_lpt_device::status_r()
{
        return m_cent_status_in->read() ^ STATUS_BUSY ^ STATUS_ACK;
}



[Linked Image from i.imgur.com]
Posted By: Golden Child

Re: Ap2000 signs of life - 08/05/20 10:46 PM

Just for fun, I thought I'd play with svgedit and inkscape to see if I could make something that looks like the control panel.

[Linked Image from i.imgur.com]
Posted By: Golden Child

Re: Ap2000 signs of life - 08/11/20 02:38 AM

More silly fun:

I was thinking about having the printer make some noise while it was printing and I was able to get it to squawk a little.


[video:youtube]https://youtu.be/nXu1cxIHsZc[/video]

I think my "pin-firing" detection is missing half of the pin firings so it's pretty quiet when printing some areas.
Posted By: Golden Child

Re: Ap2000 signs of life - 08/14/20 09:41 AM

So I wanted to see what kind of waveforms were being generated by mame audio. With ubuntu, I had to use pavucontrol to select the monitor of Built-in audio to get the system-generated sound for Audacity to record.

[Linked Image from i.imgur.com]



I did discover something interesting, that the 1-bit DAC was generating a signal when it wasn't actually doing anything. I suppose this is correct behavior, but it does answer why I am always hearing pops and crackles. When there's an audio dropout, the waveform drops to zero and there's a "click" sound.


The dac corresponds to this code:
Code

   /* audio hardware */
        SPEAKER(config, "speaker").front_center();
        DAC_1BIT(config, "dac", 0).add_route(ALL_OUTPUTS, "speaker", 0.25);
        voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
        vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);





Lowering the volume slider to zero for the 1 bit DAC makes the clicking disappear and the VU meters go down to no signal.

[Linked Image from i.imgur.com]

[Linked Image from i.imgur.com]


If you look at the recorded waveform, there's no actual sound being played, there's just a bunch of "dropouts" where other tasks are grabbing the cpu (probably because I'm doing a bunch of printf's)

Audacity's monitor shows -46 db on the VU meter.

[Linked Image from i.imgur.com]


It's interesting when I have the mockingboard enabled as there are multiple outputs which can contribute to the clicking.
If you change the volume on the different channel volumes, the biasing can constructively and destructively interfere and audacity's VU meters will go up and down.
Posted By: Just Desserts

Re: Ap2000 signs of life - 08/14/20 09:51 AM

Why not just use -wavwrite
Posted By: R. Belmont

Re: Ap2000 signs of life - 08/14/20 01:44 PM

The speaker click device the A2 uses simulates capacitive coupling because otherwise it was impossible to mix its output with a Mockingboard AY-3 or the GS's ES5503. After all, the definition of a speaker click device is that the voltage is either 0 or 5 volts, nothing in between.

Can we get back to what exactly made the AP2000 work? It was the NMI-at-startup and then something with the ADCs?
Posted By: Golden Child

Re: Ap2000 signs of life - 08/14/20 02:41 PM

Ok, sorry I tend to go off on tangents. 8-)

I think that the NMI would be fixed if it didn't hit right as it starts up, maybe delayed by a little bit.


I found the ADC conversion wasn't timing correctly.

Making some crap macros to help me see how many cycles and how much time ran in between.

Code

#define LASTPASSDIFFERENCE(t, name, func, str) \
  static t staticlast##name; \
  t last##name = staticlast##name; \
  t diff##name; \
  t cur##name = func; \
  diff##name = cur##name - staticlast##name;  diff##name=diff##name;\
  printf(#name": "); \
  printf(str "\n",cur##name-last##name);\
  printf("\n");\
  staticlast##name = cur##name;

#define LASTPASSPRINT(name, str, item) \
  printf(str "\n",item##name);




so I could do

Code
LASTPASSDIFFERENCE(long int, ADCONVSCANEACH_CYCLES, total_cycles(), "T cycles = %ld   expected to see 192");
LASTPASSDIFFERENCE(double,  ADCONVSCAN_TIME,   machine().time().as_double(), "time = %e");
LASTPASSDIFFERENCE(long int, ADCONVSCAN_CYCLES, total_cycles(), "T cycles = %ld   expected to see 768");

LASTPASSDIFFERENCE(double,   ADCONVSCAN_TIME,   machine().time().as_double(), "time = %e");
LASTPASSDIFFERENCE(long int, ADCONVSCAN_CYCLES, total_cycles(), "T cycles = %ld   expected to see 768");
//printf("m_adcnt = %d\n",m_adcnt);
//LASTPASSPRINT(ADCONVSCAN_CYCLES, "T last = %ld", last);
//LASTPASSPRINT(ADCONVSCAN_CYCLES, "T cur = %ld", cur);
//LASTPASSPRINT(ADCONVSCAN_CYCLES, "T diff = %ld", diff);




so now I get something that looks pretty good and it fixes the super fast beeping when you press a control panel button.


Code
ADCONVSCANEACH_CYCLES: T cycles = 190   expected to see 192

ADCONVSCANEACH_CYCLES: T cycles = 195   expected to see 192

ADCONVSCANEACH_CYCLES: T cycles = 194   expected to see 192

ADCONVSCANEACH_CYCLES: T cycles = 190   expected to see 192

ADCONVSCANEACH_CYCLES: T cycles = 188   expected to see 192



I'll try to work up a patch, it doesn't change very much in the code.
Posted By: R. Belmont

Re: Ap2000 signs of life - 08/14/20 03:38 PM

Ok, that's useful, thanks!

AJR, any thoughts on the ADC timing GC observed?
Posted By: AJR

Re: Ap2000 signs of life - 08/14/20 04:31 PM

I'm not AWJ, but I'll add a few thoughts anyway.

If this really is a problem with inexact timing, then that exemplifies a common problem with MAME's MCU cores, many of which just execute each instruction all at once and then go back and run the timers and timer-based peripherals for the same number of cycles. This works fine for purely internal interrupt timers but often fails for more sensitive cases such as serial ports.

In the past, Vas Crabb has suggested "separate icount and bcount" as the one proper solution to this problem, but much like the modern floppy system (which at least does have some readable technical documentation), only Olivier Galibert seems to have fully mastered its implementation details. While I only half-understand how it works, I'm not convinced of its effectiveness as a solution, especially after finding that Olivier Galibert's MCS-96 core, despite having this thing called "bcount" (not defined in MAME's execution core), triggers high-speed outputs at the wrong times.
Posted By: Golden Child

Re: Ap2000 signs of life - 08/14/20 08:02 PM

Oh, I don't think it needs to be exactly 192 T-states, (the upd7810 has 3 clock cycles to a T-state I think) it just has to be around that. The timing doesn't need to be anywhere that exact. Once it does 4 analog measurements (4 * 192) it should be around 768 T states before it will fire an INTAD interrupt.
Posted By: Golden Child

Re: Ap2000 signs of life - 08/15/20 12:44 AM

Ok, I looked at it again, and the original code doesn't seem to have timing problems. I possibly (probably) screwed up the code while I was doing some experiments and trying to figure out what it actually does. (and then thought it was the original code)


I made a pull request for a few things on the upd7810 and the ap2000, if it's horrible let me know.

The NMI problem is still there, but the ap2000 controls seem to be working with just minor changes. It starts up in the "offline" mode so if you hit keypad 0 it will put it online.

Posted By: Golden Child

Re: Ap2000 signs of life - 08/15/20 11:30 AM

I fiddled and fiddled and couldn't get the ap2000 to go past the initialization. It was totally baffling. I put in delays and delays and hit the NMI multiple times.

Then I read the datasheet over and over again and I got a clue:

[Linked Image from i.imgur.com]

It says that you can sample the NMI input by using SKIT and SKNIT.

So it hits the SKIT NMI at $011E and never skips past the JMP $0000.

Code
010A: 48 48       SKIT    FAD
010C: 48 48       SKIT    FAD
010E: FD          JR      $010C
010F: 53          DCR     C
0110: FB          JR      $010C
0111: 4C E1       MOV     A,CR1
0113: 74 4A 02    ONI     B,$02
0116: C5          JR      $011C
0117: 37 CA       LTI     A,$CA
0119: 6A FD       MVI     B,$FD
011B: E8          JR      $0104
011C: 37 CA       LTI     A,$CA
011E: 48 40       SKIT    NMI
0120: 54 00 00    JMP     $0000


Code
--- a/src/devices/cpu/upd7810/upd7810_opcodes.cpp
+++ b/src/devices/cpu/upd7810/upd7810_opcodes.cpp
@@ -343,7 +343,7 @@ void upd7810_device::DIV_C()
 /* 48 40: 0100 1000 0100 0000 */
 void upd7810_device::SKIT_NMI()
 {
-       if (IRR & INTNMI)
+       if (IRR & INTNMI || m_nmi)
                PSW |= SK;
        IRR &= ~INTNMI;
 }
@@ -487,7 +487,7 @@ void upd7810_device::SKIT_SB()
 /* 48 60: 0100 1000 0110 0000 */
 void upd7810_device::SKNIT_NMI()
 {
-       if (0 == (IRR & INTNMI))
+       if (0 == (IRR & INTNMI) || !m_nmi)
                PSW |= SK;
        IRR &= ~INTNMI;
 }


So I think that would be right, setting the skip flag if m_nmi is set for SKIT_NMI and if m_nmi is not set.

This gets it past this spot so it will start up.
Posted By: AJR

Re: Ap2000 signs of life - 08/15/20 05:16 PM

That datasheet is a bit misleading. As a later manual explains, SKIT NMI and SKNIT NMI do not actually test INTFNMI (which makes sense since the flip-flop is cleared as soon as a NMI is taken and a NMI must always be taken), only the actual level of the NMI pin.
Posted By: Golden Child

Re: Ap2000 signs of life - 08/15/20 06:56 PM


Hi AJR,

Yes, I think I understand now exactly what that means. The subtle distinctions make all the difference. Thanks for fixing this.


With my latest changes the ap2000 should start up properly and go "on-line" without having to manually hit the "on-line button".




It still drops characters though, do you guys have any objections to having a buffer to hold the incoming overflow characters until it's figured out?
Posted By: R. Belmont

Re: Ap2000 signs of life - 08/15/20 08:31 PM

If it's all working now I'd like to look at the A2 parallel cards again and see if I have the handshake wrong or something.
Posted By: Golden Child

Re: Ap2000 signs of life - 08/15/20 09:10 PM

Hi RB, I think it pretty much works now except for dropping chars if my latest commit is added.
Posted By: R. Belmont

Re: Ap2000 signs of life - 08/15/20 10:20 PM

Yeah, I just saw that commit go in, great!
Posted By: Golden Child

Re: Ap2000 signs of life - 08/16/20 11:22 AM


Throwing in a buffer in between gets us Reggie!


Code
 
 WRITE_LINE_MEMBER( e05a30_device::centronics_input_strobe )
 {

        // using a buffer to hold the incoming data when printer can't keep up.
        // This is obviously not correct, but until the answer is found,
        // allows the ap2000 to function without dropping characters.

//     if (m_centronics_strobe == true && state == false && !m_centronics_busy) {
       if (m_centronics_strobe == true && state == false) {

           if (m_centronics_data_latched) { // will lose data, so put into buffer
               minibuffer[minibufferhead] = m_centronics_data;
               minibufferhead ++;
               minibufferhead %= minibuffersize;
           }
           else {
               m_centronics_data_latch   = m_centronics_data;
 
                m_centronics_data_latched = true;
                m_centronics_busy         = true;
                m_write_centronics_busy(m_centronics_busy);
            }
        }
 
        m_centronics_strobe = state;
@@ -203,6 +219,15 @@ uint8_t e05a30_device::read(offs_t offset)
        case 0x03:
                result = m_centronics_data_latch;
                m_centronics_data_latched = false;
+
+               if (minibufferhead != minibuffertail) {
+                       m_centronics_data_latch   = minibuffer[minibuffertail++];
+                       minibuffertail %= minibuffersize;
+                       m_centronics_data_latched = true;
+                       m_centronics_busy         = true;
+                       m_write_centronics_busy(m_centronics_busy);
+                }
+
                break;
        case 0x04:
                result |= m_centronics_busy << 0;
diff --git a/src/devices/machine/e05a30.h b/src/devices/machine/e05a30.h
index 5dfb51ac81c..d7220c4bc89 100644
--- a/src/devices/machine/e05a30.h
+++ b/src/devices/machine/e05a30.h
@@ -76,6 +76,11 @@ private:
        uint8_t m_centronics_strobe;
        uint8_t m_centronics_data_latch;
        uint8_t m_centronics_data_latched;
+
+       static const int minibuffersize=1e6;  // temporary fix for dropping characters
+       int minibuffer[minibuffersize];
+       int minibufferhead;
+       int minibuffertail;
 };
 
 DECLARE_DEVICE_TYPE(E05A30, e05a30_device)




[Linked Image from i.imgur.com]

Playing with Amiga graphic dump:

[Linked Image from i.imgur.com]

Interesting that the a2 PIC Parallel firmware seems to be slightly better than the Centronics in that you don't get it sending 9E and 1D to the printer (hardcoded in the firmware for switching a Centronics Microprinter into 40 and 80 column mode).

Appleworks apple+H screen dump:

[Linked Image from i.imgur.com]
Posted By: R. Belmont

Re: Ap2000 signs of life - 08/16/20 12:33 PM

What are your DIP switch settings? I have some idea how to fix it without a buffer, but I can't get any program (including Triple-Dump) to print much of anything.
Posted By: Golden Child

Re: Ap2000 signs of life - 08/16/20 12:47 PM

Hi RB,

I think it's pretty much the "default" DIP settings I'm using now:

[Linked Image from i.imgur.com]

You can see what the ap2000 actually receives in its buffer by doing this in the debugger:

focus 1 (this selects the ap2000 upd7810 cpu)
ctrl+M
8000 (the internal ap2000 buffer is at $8000)


Here you can see the ap2000 getting 9E and 1D as the first characters when I've got the centronics firmware selected on the PIC.
[Linked Image from i.imgur.com]


quick and dirty: apple 2 ctrl+reset PR#1 then just type a bunch of keys and the printer will print junk:


or another idea (since the control panel keys are working now:)

when you start up mame, hold down the keypad 7 and 9 keys (LF and FF) and that will put the printer into Data Dump Mode where it displays the hex sent. It won't print anything until it gets a line of text, but you can override that by toggling keypad 0 (online/offline) and that will print the last characters sent.
Posted By: Golden Child

Re: Ap2000 signs of life - 08/16/20 01:03 PM

I can't remember exactly, but I had a lot of problems getting data to the printer too:

It may even be this line in e05a30.cpp:

if (m_centronics_strobe == true && state == false && !m_centronics_busy) {

if you drop the !m_centronics_busy part, data should definitely be flowing.
Posted By: Golden Child

Re: Ap2000 signs of life - 08/22/20 04:37 AM

Just for fun, I thought I'd try to hook up a rom for the Apple II Epson APL interface card using the Apple2 PIC as a model. I was able to get it working with an interesting issue. It has some really strange code that wants to read $c1c1. My workaround was to see if it had just read from that address, and if so, return 0.


so the slot number is in x so it ors with $c0, making it $c1, stores it in $01. Then stores $c1 into $00.

Then it keeps reading $c1c1 until it doesn't have the high bit set. I think this could be patched to check the busy address of the Apple2 PIC.

Code
C990: 48       pha
C991: 8A       txa
C992: 09 C0    ora #$c0
C994: 85 01    sta $01
C996: A9 C1    lda #$c1
C998: 85 00    sta $00
C99A: A0 00    ldy #$00
C99C: B1 00    lda ($00), y
C99E: 30 FC    bmi $c99c
C9A0: 8A       txa
C9A1: 0A       asl a
C9A2: 0A       asl a
C9A3: 0A       asl a
C9A4: 0A       asl a
C9A5: A8       tay
C9A6: 68       pla
C9A7: 99 80 C0 sta $c080, y
C9AA: 28       plp
C9AB: 60       rts



Otherwise, it seems to work ok, it doesn't pass 8 bits through, just 7 bits. That probably explains why Triple-Dump has such short graphical sequences, as it only sends 127 bytes of graphics data at a time so you see it doing little horizontal strips instead of a whole line at a time. It's actually super good for use with Apple II basic as it ends up stripping the high bit out.

Strangely, the CTRL+I codes don't match up with another Epson interface card manual. Anyone have an Epson APL card manual?

I can only really use CTRL+I G to do hi-res graphic dumps. So for example: CTRL+I G D I 2 space will do a graphic dump at double density, inverse and do page 2.

Also CTRL+Q by itself will dump the hi-res screen (just like the Silentype.)

Code
   100 HGR : HCOLOR = 3
   110 HPLOT 0,0 TO 279,0 : HPLOT 279,0 TO 279,191 : HPLOT 279,191 TO 0,0 : HPLOT 0,0 TO 0,191
   120 HPLOT 0,191 TO 279,191 : HPLOT 0,191 TO 279,0
   130 DATA "B","SIDE BY SIDE"
   140 DATA "A","AND PAGE 1+2"
   150 DATA "O","OR PAGE 1+2"
   160 DATA "H","XOR PAGE 1+2"
   170 DATA "I","INVERSE"
   180 DATA "E","DOUBLE SIZE"
   190 DATA "D","DOUBLE DENSITY"
   200 DATA "L","LAST LINE?"
   210 DATA "2","PAGE 2"
   220 DATA "END","END"
   300 READ A$,B$
   305 IF A$="END" THEN GOTO 400
   290 PR #1
   310 PRINT "CTRL+I G ";B$:PRINT CHR$(9)"G"A$
   320 GOTO 300

   399 REM CTRL+I G L WILL PRINT THE GFX SCREEN LINES THAT THE TEXT CURSOR IS ON
   400 ? CHR$(27)"A"CHR$(8):FOR I=0 TO 23:POKE 37,I:? CHR$(9)"GL ";:? CHR$(27)"A"CHR$(8):NEXT


[Linked Image from i.imgur.com]

Here's gfx page 1 and 2 side by side,
then gfx page 1 AND gfx page 2,
then gfx page 1 OR gfx page 2:

[Linked Image from i.imgur.com]

Seems to work ok with Triple Dump:
(discovered that the Epson FX-80 driver in Triple Dump is buggy and needed to use "Triple Dump (Beagle Bros. - 1984-10-22update).dsk" to do 80/72/90 dpi modes.)
[Linked Image from i.imgur.com]
Posted By: Golden Child

Re: Ap2000 signs of life - 08/22/20 06:01 PM

I was able to get the Epson APL to work, why not try a Grappler Plus Parallel Interface rom that's 4K.

After not getting the bank switching right, I finally got it!

And now I can do rotated graphics with CTRL+I G R <CR>. Yay!

[Linked Image from i.imgur.com]

With the Grappler Plus, you can use an asterisk to set the Epson graphics mode from 1 to 6 so you can do 80/72/90 dpi as well as 60/120/240.

CTRL+I G * 4 <CR> will do 80 dpi.

[Linked Image from i.imgur.com]
Posted By: Golden Child

Re: Ap2000 signs of life - 09/06/20 09:23 AM


I was thinking about how it'd be interesting to write a "printer" simulator in lua so I could render various printer outputs that have different ESC codes... like Imagewriter ESC codes, 'cuz I'm dying to print dot matrix output in color.

I made a luaprinter class and I've got it so it can render to a bitmap.

Just a proof of concept.

Code
class luaprinter {

public:
        luaprinter(){};

        const static int BUFFERSIZE = 128000;  // a nice big size so we shouldn't have to worry
        int m_printerbuffer[BUFFERSIZE];
        int m_head = 0;
        int m_tail = 0;
        bitmap_rgb32 *m_bitmap;  // pointer to bitmap
        int m_xpos = 0;
        int m_ypos = 0;

        virtual void clearpage(){ m_bitmap->fill(0);};
        virtual void drawpixel(int x, int y, int pixelval){m_bitmap->pix32(y,x) = pixelval; };  // row major
        virtual int getpixel(int x, int y){return m_bitmap->pix32(y,x);};
        virtual void setheadpos(int x, int y){m_xpos=x;m_ypos=y;};
        virtual void savepage(){};
        virtual std::tuple<int*,int,int>  getbuffer() { return std::make_tuple(m_printerbuffer,m_head,m_tail);};   // returns the entire buffer as an integer a>
        virtual int getnextchar(){if (m_head==m_tail) return -1; else { int retval = m_printerbuffer[m_tail++]; m_tail %= BUFFERSIZE; return retval;}};
        virtual void putnextchar(int c){m_printerbuffer[m_head++]=c; m_head %= BUFFERSIZE;};
        void register_bitmap(bitmap_rgb32 &mybitmap){m_bitmap = &mybitmap;}  //
        void  testmodifybuffer(){ for (int i=0;i<10;i++){  m_printerbuffer[i]=i; m_head++;  };  };
        std::tuple<int,int>getheadpos() { return std::make_tuple(m_xpos,m_ypos); };

        static std::vector<luaprinter *> luaprinterlist;
};


and then hack on centronics/printer.cpp to inherit from luaprinter, and do a little bit of hookups in luaengine.

Code
        auto luaprinter_type = sol().registry().create_simple_usertype<luaprinter>("new", sol::no_constructor);
        luaprinter_type.set("clearpage", &luaprinter::clearpage);
        luaprinter_type.set("drawpixel", &luaprinter::drawpixel);
        luaprinter_type.set("getpixel", &luaprinter::getpixel);
        luaprinter_type.set("setheadpos", &luaprinter::setheadpos);
        luaprinter_type.set("savepage", &luaprinter::savepage);
        luaprinter_type.set("getbuffer", &luaprinter::getbuffer);
        luaprinter_type.set("getnextchar", &luaprinter::getnextchar);
        luaprinter_type.set("getheadpos", &luaprinter::getheadpos);
        sol().registry().set_usertype("luaprinter", luaprinter_type);

        machine_type.set("luaprinters", sol::property([this](running_machine &m) {
                        sol::table table = sol().create_table();
                        int i=0;
                        for(luaprinter* p : luaprinter::luaprinterlist)
                        {
                                table[i++] = &(*p);
                        };
                        return table;
                }));



I haven't worked it all out yet and I'm figuring out all this cpp stuff (and sometimes not figuring it out 8-) but I did get it to draw on my bitmap:
Code
for i=0,255 do for p=0,7 do 
if (2^p) & i ~= 0 then 
   manager:machine().luaprinters[0]:drawpixel(i,20+p,0) 
   manager:machine().luaprinters[0]:setheadpos(i,20) 
end end end

[Linked Image from i.imgur.com]

And it wouldn't be hard at all to do color:
[Linked Image from i.imgur.com]
Code
function iff(a,b,c) if a~=0 then return b else return c end end
for i=0,255 do 
for p=0,7 do 
if (2^p) & i ~= 0 then 
   manager:machine().luaprinters[0]:drawpixel(i,20+p,iff((2^1)&p,0xff0000,0)|iff((2^2)&p,0xff00,0)|iff((2^3)&p,0xff,0)) 
   manager:machine().luaprinters[0]:setheadpos(i,20) 
end end end
Posted By: Golden Child

Re: Ap2000 signs of life - 09/07/20 04:14 AM

I was able to get my luaprinter to "print" something from Zoom Graphics pretending to be an Apple DMP:
[Linked Image from i.imgur.com]


And the lua code looks like this:

Code
function asc(c) return string.byte(c) end

function getnnnn()
  local i local retval=0 for i=3,0,-1 do ch=coroutine.yield() if ch >= asc('0') and ch <= asc('9') then retval = retval + (ch-asc('0'))*10^(i) end end return retval end

function getn(n)
  local i local retval=0 for i=n-1,0,-1 do ch=coroutine.yield() if ch >= asc('0') and ch <= asc('9') then retval = retval + (ch-asc('0'))*10^(i) end end return retval end

function renderhead(v) for i=0,7 do if (v & (2^i))~=0 then lp0:drawpixel(xpos,ypos+i,0) end end end

function dogfx() ch=coroutine.yield() renderhead(ch) xpos=xpos+1 lp0:setheadpos(xpos,ypos) end

function renderprt(ch) 
local xdpi,ydpi,feed,lfdir
xdpi = 144
ydpi = 72
feed=144/8
xpos=0
ypos=0
while 1 do 
ch = coroutine.yield() 
--print ("renderprt: "..ch.." "..string.char(ch)) 
if ch == 27 then
  ch = coroutine.yield()
  if ch == asc('n') then dpi=72
  elseif ch == asc('N') then xdpi=80
  elseif ch == asc('E') then xdpi=96
  elseif ch == asc('p') then xdpi=144
  elseif ch == asc('P') then xdpi=160
  elseif ch == asc('e') then xdpi=107
  elseif ch == asc('q') then xdpi=120
  elseif ch == asc('Q') then xdpi=136
  elseif ch == asc('f') then lfdir=1
  elseif ch == asc('r') then lfdir=-1
  elseif ch == asc('L') then lm=getn(3)
  elseif ch == asc('>') then bidir=0
  elseif ch == asc('<') then bidir=1
  elseif ch == asc('A') then feed=144/6  -- 24
  elseif ch == asc('B') then feed=144/8  -- 18
  elseif ch == asc('T') then feed=getn(2)
  elseif ch == asc('G') then nchars=getn(4)   for i=1,nchars do dogfx() end
  elseif ch == asc('S') then nchars=getn(4)   for i=1,nchars do dogfx() end
  elseif ch == asc('g') then nchars=getn(3)*8 for i=1,nchars do dogfx() end
  elseif ch == asc('V') then nchars=getn(4)   
                             ch=coroutine.yield() for i=1,nchars do renderhead(ch) end
  elseif ch == asc('F') then xpos = getn(4)
  elseif ch == asc('V') then -- set tof
  elseif ch == asc('O') then -- paper detect off
  elseif ch == asc('o') then -- paper detect on
  elseif ch == asc('!') then -- start bold
  elseif ch == asc('"') then -- end bold
  elseif ch == asc('X') then -- start underline
  elseif ch == asc('Y') then -- end underline
  else -- gobble char
  end
elseif ch == 13 then xpos = 0    -- cr
elseif ch == 10 then ypos = ypos + feed/144*ydpi xpos = 0  -- lf
elseif ch == 12 then  -- formfeed
end
end 
end

corenderprt = coroutine.create(renderprt)
coroutine.resume(corenderprt)

lp0 = manager:machine().luaprinters[0]

function feedchars(ch)
repeat
nextchar = lp0:getnextchar()
if nextchar >= 0 then coroutine.resume(corenderprt,nextchar) end
until nextchar < 0
end

function framedispatch() for i,j in pairs(dispatchlist) do j() end end
emu.register_frame(framedispatch)
dispatchlist={feedchars}



Printing from the NewsRoom demo:

[Linked Image from i.imgur.com]
Posted By: Golden Child

Re: Ap2000 signs of life - 09/08/20 01:34 AM

I thought, let's see if we can print color so I made some modifications to do color.

I looked high and low for a program that would print in color on the Apple II and I was able to get my luaprinter to print in color with Printographer. You can choose which Apple II hi-res colors match with specific color ribbons. Ribbon 1 being Yellow, 2 Magenta and 3 Cyan.


[Linked Image from i.imgur.com]

[Linked Image from i.imgur.com]
Posted By: Golden Child

Re: Ap2000 signs of life - 09/10/20 08:46 AM

I made a luaprinter for both centronics and rs232 and was having some trouble sorting out why it was dropping characters for the serial port.

Still sorting it out, gonna try a mutex, but I thought why not try to "replay" a print job to the lua printer.

It's pretty easy, just put chars into the buffer with putnextchar(). First I had to add putnextchar to luaengine which was trivial.

Code
        luaprinter_type.set("getnextchar", &luaprinter::getnextchar);
        luaprinter_type.set("putnextchar", &luaprinter::putnextchar);



I made a printout with the regular serial printer, and -printout test.txt to send it to a file.

Then did this from the console:
Code
dofile("../../luaprinter.lua")
f = io.open("test.txt")
filedata = f:read("*a")
print(#filedata)
for i=1,#filedata do lp0:putnextchar(string.byte(filedata,i)) end


and to "print" it again, this time with a different xdpi for instance:

Code

xpos=0 ypos=0 lp0:clearpage() paperxdpi=72 for i=1,#filedata do lp0:putnextchar(string.byte(filedata,i)) end



Of course this is only going to work if it fits entirely into the buffer.

[Linked Image from i.imgur.com]

Posted By: rfka01

Re: Ap2000 signs of life - 09/10/20 01:19 PM

That's really neat stuff you're coaxing the system into doing ... major thumbs up!
Robert
Posted By: Golden Child

Re: Ap2000 signs of life - 09/10/20 04:39 PM

Thanks Robert!



I figured out what was wrong with my serial luaprinter, it was that I used a char variable instead of a u8 and it was converting 128-255 into a negative number. (That's what I get for growing up with Pascal CHAR types 8-) It's got to be unsigned char.

Code
void serial_luaprinter_device::rcv_complete()
{
        receive_register_extract();
        u8 recchar = get_received_char();
        m_printer->output(recchar);
        putnextchar(recchar);
}



so now the Amiga ImagewriterII driver can do this:

[Linked Image from i.imgur.com]

Oddly, printing out of the serial port seems faster than out of the parallel port.
Posted By: Golden Child

Re: Ap2000 signs of life - 09/11/20 08:33 AM

Managed to get DOS Instant Artist printing, seemed to get hung up on some of the lpt status bits, specifically the paper out bit, so ^ 0x20 seemed to fix it.


[Linked Image from i.imgur.com]
Posted By: R. Belmont

Re: Ap2000 signs of life - 09/11/20 12:18 PM

That's cool. The IW2 was serial only though, so I'm not quite understanding the LPT aspect smile Also, I had no idea the IW2 was supported by software on non-Apple systems.
Posted By: Vas Crabb

Re: Ap2000 signs of life - 09/11/20 03:03 PM

ImageWriter II is well-supported on Windows at least until Windows XP. You can get a Bitronics-RS422 bridge to use it on an LPT port if you really want to. "Standard" Windows printer drivers assume that the same high-level byte-oriented protocol can be used to communicate with a printer whether it's on a parallel port (Bitronics or ECP), serial, or a TCP socket connection. You can thank HP for pioneering the nybble-oriented Bitronics back-channel, and their dumb print server modules that just exposed that to a TCP socket.
Posted By: Golden Child

Re: Ap2000 signs of life - 09/11/20 03:39 PM

Since most printers are byte-oriented, perhaps we could have a parallel to serial converter and a serial to parallel converter.

Then you could use the ap2000 on a system that only supports serial, for example.

I made a serial luaprinter and added it to nano src/devices/bus/isa/com.cpp so you can do this:

(I did a MODE COM2:9600,N,8,1 before launching instant artist just for good measure)

[Linked Image from i.imgur.com]

[Linked Image from i.imgur.com]



I was going to see if I could get the coco3 to do the luaprinter (maybe getting a CGP-220 driver going) but it freezes up on a PRINT #-2. Also there's some strange double screen action going on.

[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]
Posted By: Golden Child

Re: Ap2000 signs of life - 09/11/20 06:34 PM

I changed the baud rate of the serial printer to 2400 in the source code and could get bytes from the c64 but only on the user port channel 2.

Printers are supposed to be on channel 4 or 5 on the c64 iec bus, however there aren't any iec drivers that work, there's vic1515 but it's just a skeleton.

I was really keen on trying to get an okimate 20 print going, since its graphics commands are pretty simple and I had always wanted an oki.

I can get the user port to connect and send bytes.

[Linked Image from i.imgur.com]

[Linked Image from i.imgur.com]

But the c64 wants printers on 4...

[Linked Image from i.imgur.com]

I did find an okimate 20 apple2 disc on archive but it was in a2r format.
Posted By: Golden Child

Re: Ap2000 signs of life - 09/13/20 03:46 AM

I found an article that mentioned printer drivers for Atari ST Degas and it has a bunch of different drivers for different dot matrix printers.

Hacking on a lua script made it output something recognizable for an Okimate 20.

Consulting the document "MCS-820_Printer_Handbook_(aka_Okimate_20).pdf" was indispensable.

[Linked Image from i.imgur.com]
Posted By: Golden Child

Re: Ap2000 signs of life - 09/13/20 02:26 PM

So let's see if we can get windows 3.1 to print something.

After some fits and starts, win 3.1 installed with "SETUP /I" which disables the hardware detection.

And the ap2000 works with the Epson FX-80 driver. Cool!

[Linked Image from i.imgur.com]

and I tried the luaprinter with the c-itoh 8510 driver as I couldn't find an imagewriter II driver anywhere for windows 3.1. Unfortunately the 8510 driver doesn't do color.

[Linked Image from i.imgur.com]

Interestingly, it complained about paper being out for the luaprinter but not the ap2000, so I did the ^0x20 to the status just to get it to work.
Posted By: Golden Child

Re: Ap2000 signs of life - 09/13/20 04:06 PM

Just for fun, I added a buffer indicator to the ap2000. The buffer size is shown by the little green bars in the upper left of the printout. Each bar represents a hex digit of the size. It's kinda fun to watch the bars grow and shrink as the buffer fills and clears.

It's also a good indicator of whether the system is properly respecting the busy/ack signals as it will never use the buffer if so.

[Linked Image from i.imgur.com]
Posted By: Golden Child

Re: Ap2000 signs of life - 09/14/20 01:07 PM

Adding output_perror(0) seems to fix the paper out problems:

Code
void centronics_luaprinter_device::device_reset()
{
        printf("DEVICE RESET CALLED\n");
        m_busy = false;
        output_busy(m_busy);
        output_fault(1);
        output_ack(1);
        output_ack(0);
        output_select(1);
        output_perror(0); // added paper out
}


So let's see if Geos 2.0 will print something:

[Linked Image from i.imgur.com]
Posted By: Golden Child

Re: Ap2000 signs of life - 09/14/20 04:10 PM


And if win3.1 works, why not try win 95?

(installing from floppies and using the file manager is so tedious! but it works!)

Luaprinter:

[Linked Image from i.imgur.com]

Ap2000:

[Linked Image from i.imgur.com]
Posted By: R. Belmont

Re: Ap2000 signs of life - 09/14/20 06:03 PM

Neat.
Posted By: Golden Child

Re: Ap2000 signs of life - 09/15/20 11:14 PM

Thanks, RB!

I think I've got the saving the printed page nearly figured out. Here's some samples from apple II printographer printing to the Apple Scribe.

(The colors don't quite match up to the apple's color palette)

Printographer wants violet to be ribbons 2+3 but that makes it dark purple, just ribbon 2 (magenta) makes a good purple.

Apple from Zoom Graphics Disk:

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

Olympics from Joe Drish pictures:

[Linked Image from i.imgur.com]
Posted By: Golden Child

Re: Ap2000 signs of life - 09/16/20 03:36 PM

I was trying to clean up my code and put some things into the luaprinter constructor so they would be done automatically done, but it seems to make it not work. So strange. And printfs in the constructor don't appear until I exit mame.


The printfs that make "Scooby 8510" and "Scooby 8511" don't appear until exiting mame, yet the initvalue gets set properly to 3333.

But if I move routines into the constructor all sorts of weird things happen. So I'll leave it outside for now since I've been fiddling with this for a day...gcc problems on Ubuntu?


Code
luaprinter(device_t & thisdevice, int testvalue){ 
        m_lp_mydevice = &thisdevice; 
        time(&m_lp_session_time);  
        initvalue = testvalue;
        printf("\n\nInit Luaprinter Scooby %d\n",testvalue);
        initvalue = 33333;
        };




Code
[MAME]> lp = manager:machine().printers for i=1,#lp do print( lp[i]:getprintername(), #lp, lp[i]:getinitvalue(), lp[i]:simplename()) end
2020-09-16 08-25-19 apple2p-sl1-parallel-pic_ctx-luaprinter	3	33333	apple2p a2bus_slot a2pic centronics centronics_luaprinter centronics
2020-09-16 08-25-19 apple2p-sl2-ssc-ssc_rs232-luaprinter	3	33333	apple2p a2bus_slot a2ssc rs232 serial_luaprinter rs232
2020-09-16 08-25-19 apple2p-sl4-parallel-pic_ctx-ap2000	3	33333	apple2p a2bus_slot a2pic centronics ap2000 centronics


(exit mame here)

[MAME]> 

Init Luaprinter Scooby 8510

Init Luaprinter Scooby 8511

Init Luaprinter Scooby 810
Average speed: 100.00% (31 seconds)
sdl_kill: closing audio
Enter sdlwindow_exit
Leave sdlwindow_exit


after putting code in the constructor I get strange behavior:

Code
[MAME]> print( manager:machine().luaprinters[1]:getprintername(), #manager:machine().luaprinters)
error: 	std::bad_alloc
[MAME]> print( #manager:machine().luaprinters)
56
Posted By: Lord Nightmare

Re: Ap2000 signs of life - 09/16/20 07:06 PM

Does the lua interface allow you to force fflush on stdout and stderr? I know there's some really bizarre issues in mingw/msys2 with stderr not fflush()ing itself instantly (like it does on POSIX systems) on windows.

LN
Posted By: Golden Child

Re: Ap2000 signs of life - 09/16/20 08:32 PM

Hi LN,

Yes, fflush(stdout); does the trick. Thanks.

so I'm just curious now why there's so many printf's when I should only have 3 luaprinter devices
Code
luaprinter::luaprinter(device_t& thisdevice, int testvalue){ 
	m_lp_mydevice = &thisdevice; 
	time(&m_lp_session_time);  
	initvalue = testvalue;
	printf("yes you can");        // putting in a printf here
	fflush(stdout);
	
	};


Code
 ./mame64 apple2p  -sl1 parallel -sl1:parallel:pic_ctx luaprinter -flop1 ../../printographer.dsk -sl2 ssc -sl2:ssc:ssc_rs232 luaprinter -sl4 parallel -sl4:parallel:pic_ctx ap2000 -verbose

yes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canyes you canAttempting load of mame.ini
...

    _/      _/    _/_/    _/      _/  _/_/_/_/
   _/_/  _/_/  _/    _/  _/_/  _/_/  _/       
  _/  _/  _/  _/_/_/_/  _/  _/  _/  _/_/_/    
 _/      _/  _/    _/  _/      _/  _/         
_/      _/  _/    _/  _/      _/  _/_/_/_/    

mame 0.224	
Copyright (C) Nicola Salmoria and the MAME team

Lua 5.3	
Copyright (C) Lua.org, PUC-Rio

...
yes you canyes you canyes you canAttempting load of raster.ini
Attempting load of source/apple2.ini
Attempting load of apple2.ini
Attempting load of apple2p.ini
yes you canyes you canyes you canAvailable videodrivers: x11 wayland dummy 
Posted By: Golden Child

Re: Ap2000 signs of life - 09/16/20 09:11 PM

So my concept is to use the luaprinter class to provide a way to save the bitmap from a driver that doesn't really need the lua parts, just the printing parts. The lua stuff is there, but the driver doesn't need to use them.


So we can inheirit from luaprinter:

Code
class epson_lx810l_device :
public device_t, 
public device_centronics_peripheral_interface, 
public luaprinter
{
...

epson_lx810l_device::epson_lx810l_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
        device_t(mconfig, type, tag, owner, clock),
        device_centronics_peripheral_interface(mconfig, *this),
        luaprinter(*this, 810),
... 


and then we can do some things in the device_start:

Code
void epson_lx810l_device::device_start()
{
	m_online_led.resolve();

	m_cr_timer = timer_alloc(TIMER_CR);

	m_screen->register_screen_bitmap(m_bitmap);
	m_bitmap.fill(0xffffff); /* Start with a clean white piece of paper */


// do the luaprinter stuff, I would like to do more in the constructor, but it seems to cause problems.

	register_bitmap(m_bitmap);  // register with luaprinter
	luaprinterlist.emplace_back(static_cast<luaprinter *>(this));
	setprintername(sessiontime()+std::string(" ")+tagname());




and then you can save the bitmap with:

MAME]> print(manager:machine().lp[3]:pageheight())
576
[MAME]> print(manager:machine().lp[3]:pagewidth())
1024
[MAME]> manager:machine().lp[3]:savepage()
[MAME]> print(manager:machine().lp[3]:getprintername())
2020-09-16 13-53-53 apple2p-sl4-parallel-pic_ctx-ap2000
[MAME]>

So here's the page saved out:
[Linked Image from i.imgur.com]
Posted By: Golden Child

Re: Ap2000 signs of life - 09/16/20 09:30 PM

and the luaprinter code is actually pretty short:

Code

#ifndef MAME_LUAPRINTER_H
#define MAME_LUAPRINTER_H

#pragma once

#include "emu.h"
#include "png.h"
#include "emuopts.h"

class luaprinter {

public:

	int initvalue;
	device_t * m_lp_mydevice;
	luaprinter(device_t & thisdevice, int testvalue);

	static std::vector<luaprinter *> luaprinterlist;

	const static int BUFFERSIZE = 128000;
	std::array<unsigned char, BUFFERSIZE>  m_printerbuffer;
	int m_lp_head = 0;
	int m_lp_tail = 0;
	bitmap_rgb32 *m_lp_bitmap;  // pointer to bitmap
	int m_xpos = 0;
	int m_ypos = 0;
	std::string m_luaprintername;
	int m_page_count;
	static time_t m_lp_session_time;

	void addtolist(luaprinter & myprinter){ luaprinterlist.emplace_back(& myprinter);}
	void setprintername(std::string name){ m_luaprintername = name; }
	std::string getprintername(){ return m_luaprintername; }

	int getinitvalue(){ return initvalue; }

	void clearpage(){ m_lp_bitmap->fill(0xffffff);};
	void drawpixel(int x, int y, int pixelval) { m_lp_bitmap->pix32(y,x) = pixelval; };
	int getpixel(int x, int y){return m_lp_bitmap->pix32(y,x);};
	void setheadpos(int x, int y){m_xpos=x;m_ypos=y;};

	int pagewidth() { return m_lp_bitmap->width(); }
	int pageheight() { return m_lp_bitmap->height(); }

	device_t* getrootdev();
	void savepage();
	
	std::tuple<std::array<unsigned char,BUFFERSIZE>&,int,int>  getbuffer() { return std::make_tuple(std::ref(m_printerbuffer),m_lp_head,m_lp_tail);};   
	int getnextchar();
	void putnextchar(int c);
	void register_bitmap(bitmap_rgb32 &mybitmap){m_lp_bitmap = &mybitmap;}
	std::tuple<int,int>getheadpos() { return std::make_tuple(m_xpos,m_ypos); };
	int count(){ return luaprinterlist.size();}
	std::string fixcolons(std::string in);
	std::string sessiontime();
	std::string tagname();
	std::string simplename();
};


#endif  // MAME_LUAPRINTER_H


luaprinter.cpp:
Code

#include "luaprinter.h"

luaprinter::luaprinter(device_t& thisdevice, int testvalue){ 
	m_lp_mydevice = &thisdevice; 
	time(&m_lp_session_time);  
	initvalue = testvalue;
	printf("yes you can");
	fflush(stdout);
	
	};

int luaprinter::getnextchar() {
	if (m_lp_head==m_lp_tail) return -1; 
	else {
		int retval = m_printerbuffer.at(m_lp_tail++); 
		m_lp_tail %= BUFFERSIZE; 
		return retval;
	}
}

void luaprinter::putnextchar(int c) {
	m_printerbuffer.at(m_lp_head++)=c; 
	m_lp_head %= BUFFERSIZE;
}

std::string luaprinter::fixcolons(std::string in) {
    std::string final;
    for(std::string::const_iterator it = in.begin(); it != in.end(); ++it)
    {
        if((*it) != ':')
        {
            final += *it;
        }
        else final += '-';
    }
    return final;
}

std::string luaprinter::sessiontime() {
   struct tm *info;
   char buffer[120];
   info = localtime( &m_lp_session_time );
   strftime(buffer,120,"%Y-%m-%d %H-%M-%S", info);
   return std::string(buffer);
}

std::string luaprinter::tagname() {
	device_t * dev;
	device_t * lastdev;
	dev = m_lp_mydevice;
	std::string s(dev->owner()->shortname());
	while (dev) {
		lastdev = dev;
		dev=dev->owner();
	}
	lastdev=lastdev; // complains about non use
	return fixcolons(std::string(lastdev->shortname())+std::string(m_lp_mydevice->tag()));
}

std::string luaprinter::simplename() {
	device_t * dev;
	device_t * lastdev;
	dev = m_lp_mydevice;
	std::string s(dev->owner()->shortname());
	while (dev){
		s=std::string(dev->shortname())+std::string(" ")+s;
		lastdev = dev;
		dev=dev->owner();
	}
	lastdev=lastdev; // complains about non use
	return s;
}

device_t* luaprinter::getrootdev(){
	device_t* dev;
	device_t* lastdev = NULL;
	dev = m_lp_mydevice;
	while (dev){
		lastdev = dev;
		dev=dev->owner();
	}
	lastdev=lastdev; // complains about non use
	return lastdev;
}

void luaprinter::savepage(){
    emu_file file(std::string(m_lp_mydevice->machine().options().snapshot_directory()) + std::string("/") +
				std::string(getrootdev()->shortname() ) + std::string("/"), 
				OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
    auto const filerr = file.open(std::string(getprintername())+" Page "+std::to_string(m_page_count++)+".PNG");

    if (filerr == osd_file::error::NONE)
        {
            static const rgb_t png_palette[] = { rgb_t::white(), rgb_t::black() };
            // save the paper into a png
            png_write_bitmap(file, nullptr, (bitmap_t &) (* m_lp_bitmap), 2, png_palette);
        }
}




in luaengine.cpp:
Code
        auto luaprinter_type = sol().registry().create_simple_usertype<luaprinter>("new", sol::no_constructor);
        luaprinter_type.set("clearpage", &luaprinter::clearpage);
        luaprinter_type.set("drawpixel", &luaprinter::drawpixel);
        luaprinter_type.set("getpixel", &luaprinter::getpixel);
        luaprinter_type.set("setheadpos", &luaprinter::setheadpos);
        luaprinter_type.set("savepage", &luaprinter::savepage);
        luaprinter_type.set("getbuffer", &luaprinter::getbuffer);
        luaprinter_type.set("getnextchar", &luaprinter::getnextchar);
        luaprinter_type.set("putnextchar", &luaprinter::putnextchar);
        luaprinter_type.set("getheadpos", &luaprinter::getheadpos);
        luaprinter_type.set("setprintername", &luaprinter::setprintername);
        luaprinter_type.set("getprintername", &luaprinter::getprintername);
        luaprinter_type.set("fixcolons", &luaprinter::fixcolons);
        luaprinter_type.set("sessiontime", &luaprinter::sessiontime);
        luaprinter_type.set("simplename", &luaprinter::simplename);
        luaprinter_type.set("tagname", &luaprinter::tagname);
        luaprinter_type.set("count", &luaprinter::count);
        luaprinter_type.set("getinitvalue", &luaprinter::getinitvalue);
        luaprinter_type.set("pagewidth", &luaprinter::pagewidth);
        luaprinter_type.set("pageheight", &luaprinter::pageheight);

	sol().registry().set_usertype("luaprinter", luaprinter_type);




         machine_type.set("lp", sol::property([this](running_machine &m) {
                        sol::table table = sol().create_table();
                        int i=1;
                        for(auto p : luaprinter::luaprinterlist)
                        {
                        	table[i++] = p;
                        };
                        return table;
                }));
Posted By: Golden Child

Re: Ap2000 signs of life - 09/18/20 04:15 PM


I thought, why not try to send the printed PNG to the printer:


dofile('../../luaprinter2.lua') -- start up my imagewriter interpreter

(print something to the page)

manager:machine().lp[1]:savepage()
print(manager:machine().lp[1]:getprintername())
os.execute('lpr ~/"Downloads/mamegit/mame/snap/ct486/2020-09-18 08-59-47 ct486-board4-lpt-lpt-centronics-luaprinter Page 0.PNG"')

and lpr sends the PNG file to the printer.

Ubuntu uses cups, I don't know how it would work on windows.
Posted By: Golden Child

Re: Ap2000 signs of life - 09/18/20 06:34 PM

So if I add to my list of printers in the constructor, I get a whole bunch of devices in my list.

It seems to be initializing a bunch of devices that don't actually get used. It must be enumerating every possible device that uses the luaprinter.

Code
luaprinter::luaprinter(device_t& thisdevice, int testvalue){ 
	m_lp_mydevice = &thisdevice; 
	time(&m_lp_session_time);  
	initvalue = testvalue;

	addtoprinterlist( *this);
	printf("yes you can");
	printf(" device = %s ",thisdevice.tag());
	fflush(stdout);
	printf("count = %d\n",count());  // the size of the printerlist
	fflush(stdout);
	
	};


with one luaprinter device I get 19 items:

Code
./mame64 ct486   -hard1 hd128MB  -debug  -board4:lpt:lpt:centronics luaprinter -confirm_quit -ramsize 64M 
-board3:ide:ide:1 hdd -hard2 hd128MBpt -board3:ide:ide:1 hdd
yes you can device = :board4:lpt:lpt:centronics:luaprinter count = 1
...
yes you can device = :board4:lpt:lpt:centronics:luaprinter count = 9
    _/      _/    _/_/    _/      _/  _/_/_/_/
   _/_/  _/_/  _/    _/  _/_/  _/_/  _/       
  _/  _/  _/  _/_/_/_/  _/  _/  _/  _/_/_/    
 _/      _/  _/    _/  _/      _/  _/         
_/      _/  _/    _/  _/      _/  _/_/_/_/    

mame 0.224	
Copyright (C) Nicola Salmoria and the MAME team

Lua 5.3	
Copyright (C) Lua.org, PUC-Rio

yes you can device = :board4:lpt:lpt:centronics:luaprinter count = 10
yes you can device = :board2:comat:serport0:luaprinter count = 11
yes you can device = :board2:comat:serport1:luaprinter count = 12
yes you can device = :board4:lpt:lpt:centronics:luaprinter count = 13
yes you can device = :board4:lpt:lpt:centronics:ap2000 count = 14
yes you can device = :board4:lpt:lpt:centronics:lx810l count = 15
yes you can device = :board4:lpt:lpt:centronics:luaprinter count = 16
Debug Build: Disabling input grab for -debug
Debug Build: Disabling input grab for -debug
Debug Build: Disabling input grab for -debug
[MAME]> 
"hd128MB" approximately matches the following
supported software items (best match first):


"hd128MBpt" approximately matches the following
supported software items (best match first):

DEVICE START CALL luaprinterlist

DEVICE START CALL luaprinterlist

DEVICE START CALL setprintername

DEVICE RESET CALLED
DEVICE RESET CALLED


MAME debugger version 0.224 (mame0224-205-g69406ddcc71-dirty)
Currently targeting ct486 (PC/AT 486 with CS4031 chipset)
[MAME]> yes you can device = :board4:lpt:lpt:centronics:luaprinter count = 18
yes you can device = :board4:lpt:lpt:centronics:luaprinter count = 19


and if I add a second luaprinter device I get 35 total devices.


Code
/mame64 ct486  -hard1 hd128MB  -debug  -board4:lpt:lpt:centronics luaprinter -confirm_quit -ramsize 64M
 -board3:ide:ide:1 hdd -hard2 hd128MBpt -board3:ide:ide:1 hdd -board2:comat:serport1 luaprinter
yes you can device = :board4:lpt:lpt:centronics:luaprinter count = 1
...
yes you can device = :board4:lpt:lpt:centronics:luaprinter count = 8
yes you can device = :board2:comat:serport1:luaprinter count = 9
yes you can device = :board4:lpt:lpt:centronics:luaprinter count = 10
yes you can device = :board2:comat:serport1:luaprinter count = 11
yes you can device = :board4:lpt:lpt:centronics:luaprinter count = 12
yes you can device = :board2:comat:serport1:luaprinter count = 13
yes you can device = :board4:lpt:lpt:centronics:luaprinter count = 14
yes you can device = :board2:comat:serport1:luaprinter count = 15
yes you can device = :board4:lpt:lpt:centronics:luaprinter count = 16
yes you can device = :board2:comat:serport1:luaprinter count = 17
yes you can device = :board4:lpt:lpt:centronics:luaprinter count = 18
yes you can device = :board2:comat:serport1:luaprinter count = 19
yes you can device = :board4:lpt:lpt:centronics:luaprinter count = 20
    _/      _/    _/_/    _/      _/  _/_/_/_/
   _/_/  _/_/  _/    _/  _/_/  _/_/  _/       
  _/  _/  _/  _/_/_/_/  _/  _/  _/  _/_/_/    
 _/      _/  _/    _/  _/      _/  _/         
_/      _/  _/    _/  _/      _/  _/_/_/_/    

mame 0.224	
Copyright (C) Nicola Salmoria and the MAME team

Lua 5.3	
Copyright (C) Lua.org, PUC-Rio

yes you can device = :board2:comat:serport1:luaprinter count = 21
yes you can device = :board4:lpt:lpt:centronics:luaprinter count = 22
yes you can device = :board2:comat:serport0:luaprinter count = 23
yes you can device = :board2:comat:serport1:luaprinter count = 24
yes you can device = :board4:lpt:lpt:centronics:luaprinter count = 25
yes you can device = :board4:lpt:lpt:centronics:ap2000 count = 26
yes you can device = :board4:lpt:lpt:centronics:lx810l count = 27
yes you can device = :board2:comat:serport1:luaprinter count = 28
yes you can device = :board4:lpt:lpt:centronics:luaprinter count = 29
Debug Build: Disabling input grab for -debug
Debug Build: Disabling input grab for -debug
Debug Build: Disabling input grab for -debug
[MAME]> 
"hd128MB" approximately matches the following
supported software items (best match first):


"hd128MBpt" approximately matches the following
supported software items (best match first):

DEVICE START CALL luaprinterlist

DEVICE START CALL luaprinterlist

DEVICE START CALL setprintername

DEVICE RESET CALLED
DEVICE RESET CALLED
m_rs232_rxbaud read=7
rs232_rxbaud read=7


MAME debugger version 0.224 (mame0224-205-g69406ddcc71-dirty)
Currently targeting ct486 (PC/AT 486 with CS4031 chipset)
[MAME]> 

>g
[MAME]> yes you can device = :board2:comat:serport1:luaprinter count = 32
yes you can device = :board4:lpt:lpt:centronics:luaprinter count = 33
yes you can device = :board2:comat:serport1:luaprinter count = 34
yes you can device = :board4:lpt:lpt:centronics:luaprinter count = 35
Average speed: 99.93% (1 seconds)


Well, I guess as long as it works I'll keep it outside the constructor.
Posted By: Golden Child

Re: Ap2000 signs of life - 09/19/20 02:55 PM


Just for fun, I wanted to see if I could get some color postscript output from the win95 printer drivers using the QMS Colorscript 230 drivers.

Setting the spool settings to Print directly to printer and disable bidirectional support because it would put 0x14 characters into the printout.

Using the "printer" centronics device and then using mame's File manager and setting the printout to a file to save out the data.


Once done, using gv (ghostview) under Ubuntu to view the output. (I had to apt install gv)

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

What I'd like to do is to figure out some way to have it watch the printer, when there's a long pause in the output, say 15 seconds or so, then save everything to a file, so it can run gv automatically.
Posted By: Golden Child

Re: Ap2000 signs of life - 09/20/20 09:59 PM


I managed to get something working that would save the printer output bytes to separate files so you could launch a viewer on them, like gv for postscript output.

A delay of 30 seconds will separate files.


Code
lp0 = manager:machine().luaprinters[1]
filenamebase=lp0:getprintername()
filenamecount=0
idlewaitperiod=30*60
idlecount=0


function feedchars(ch)
local idleflag=0
repeat
nextchar = lp0:getnextchar()
if nextchar >= 0 then 
  idleflag=1
  if f == nil then
    filenamecount = filenamecount+1
    currentfilename = filenamebase..string.format("%04d",filenamecount)..".ps"
    f=io.open(currentfilename,"w")
    idlecount=0
  end
  f:write(string.char(nextchar))
 end 
until nextchar < 0
if idleflag==0 then
  if f~=nil then
    idlecount=idlecount+1 
    if idlecount%(60*5)==0 then print ("idle: "..idlecount/60) end
  end
else
  idlecount=0 -- reset idlecount
end
if idlecount > idlewaitperiod then
  idlecount=-1
  f:close()
  f=nil
  os.execute('gv "'..currentfilename..'" &')
  print('gv '..currentfilename)
end
end

function framedispatch() for i,j in pairs(dispatchlist) do j() end end
emu.register_frame(framedispatch)
dispatchlist={feedchars}



Code
idle: 5.0
idle: 10.0
idle: 15.0
idle: 20.0
idle: 25.0
idle: 30.0
gv 2020-09-20 14-14-25 ct486-board4-lpt-lpt-centronics-luaprinter0004.ps
Posted By: Golden Child

Re: Ap2000 signs of life - 09/23/20 05:55 AM

I managed to convert the ap2000 driver into using my luaprinter routines to do the page saving:

They look a little "squashed" since the aspect ratio is off because it's 120x72. 120x144 would probably look more normal.

Some page samples:

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

putting the first page into gimp and stretching it to 120x144:
[Linked Image from i.imgur.com]

testing to see how many lines on a page:
[Linked Image from i.imgur.com]
Posted By: Lord Nightmare

Re: Ap2000 signs of life - 09/24/20 06:05 PM

This is amazing stuff! Are you going to submit this upstream as a PR soon? I kinda want to play with it...

LN
Posted By: Golden Child

Re: Ap2000 signs of life - 09/25/20 05:44 AM

Hi LN,

Thanks! Yes, I'm almost there... 8-)

I finally figured out how to blast out my screwed up github repository with "git push --force" and that completely replaced everything. Yay!

Coming soon to a theater near you 8-)
Posted By: Golden Child

Re: Ap2000 signs of life - 09/26/20 09:44 PM

If you want to have a look at luaprinter, I have a branch at:

https://github.com/goldnchild/mame/tree/luaprinter

I need to clean it up and figure out the proper way of doing things using the device_interface mix-in.


[Linked Image from i.imgur.com]


One weird thing that the ap2000 is doing is that it's missing descenders when it prints in the Roman font. I thought initially that it wasn't getting the full 9 bits of the printhead, but it prints draft just fine as well as the Sans Serif.

Ramiro Polla (the uber-hacker behind the ap2000 driver) was cool enough to send me his ap2000 disassembly so maybe I can figure out why.
© 2020 Forums