Previous Thread
Next Thread
Print Thread
Page 1 of 6 1 2 3 4 5 6
c64 super sketch #115940 09/17/19 08:08 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
Thanks to a suggestion from rfka1, I thought I'd try my hand at figuring out the Super Sketch on the c64.

It looks like it just reads the potentiometer inputs, so let's do some driver mangling to see what happens:



Code

add some member variables to hold an analog inputs


-               m_va15(1)
+               m_va15(1),
+m_test_joy1x(*this, "TEST_analog_joystick_1_x"),
+m_test_joy1y(*this, "TEST_analog_joystick_1_y")
+

+
+required_ioport m_test_joy1x,m_test_joy1y;
+
 };
 
 
add some defines for an analog input
 
+
+#define JOYSTICK_DELTA          80
+#define JOYSTICK_SENSITIVITY    50
+#define JOYSTICK_AUTOCENTER     80
+
+

+        PORT_START("TEST_analog_joystick_1_x")      /* Joystick 1 X Axis */
+        PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X) PORT_NAME("TEST Joystick X")
+        PORT_SENSITIVITY(JOYSTICK_SENSITIVITY)
+        PORT_KEYDELTA(JOYSTICK_DELTA)
+        PORT_CENTERDELTA(JOYSTICK_AUTOCENTER)
+        PORT_MINMAX(0,0xff) PORT_PLAYER(1)
+        PORT_CODE_DEC(KEYCODE_4_PAD)    PORT_CODE_INC(KEYCODE_6_PAD)
+        PORT_CODE_DEC(JOYCODE_X_LEFT_SWITCH)    PORT_CODE_INC(JOYCODE_X_RIGHT_SWITCH)
+
+        PORT_START("TEST_analog_joystick_1_y")      /* Joystick 1 Y Axis */
+        PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y) PORT_NAME("TEST Joystick Y")
+        PORT_SENSITIVITY(JOYSTICK_SENSITIVITY)
+        PORT_KEYDELTA(JOYSTICK_DELTA)
+        PORT_CENTERDELTA(JOYSTICK_AUTOCENTER)
+        PORT_MINMAX(0,0xff) PORT_PLAYER(1)
+        PORT_CODE_DEC(KEYCODE_8_PAD)    PORT_CODE_INC(KEYCODE_2_PAD)
+        PORT_CODE_DEC(JOYCODE_Y_UP_SWITCH)      PORT_CODE_INC(JOYCODE_Y_UP_SWITCH)
+
+
 INPUT_PORTS_END
 

mangle the sid_pot reads, we'll just always return the m_joy1x or m_joy1y for cases 1,2,3.
 
READ8_MEMBER( c64_state::sid_potx_r )
 {
        uint8_t data = 0xff;
 
        switch (m_cia1->pa_r() >> 6)
        {
       
       case 1:
       case 2:
       case 3: data=m_test_joy1x->read(); break;

        }
 
        return data;
}
READ8_MEMBER( c64_state::sid_poty_r )
 {
        uint8_t data = 0xff;
 
        switch (m_cia1->pa_r() >> 6)
        {

       case 1:
       case 2:
       case 3: data=m_test_joy1y->read();
       break;
        }
 
        return data;
}


then you can change the potx and poty values with the analog input, and the digital joystick up/down/left and right will do the buttons for the pad.


To get past the initial screen put the joystick down in the lower right and press the digital down (I think that's the menu button).

[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]
some drawing (as best as I can with the numeric keypad masquerading as an analog joystick setting the analog speed/sensitivity to low values, I can't get the MouseX to map into the analog input in the UI menus)
[Linked Image from i.imgur.com]

I found a different SUPER-SKETCH.D64 but I could never get past the menu, wasted a few hours with that. There's also a .crt file but I couldn't get it to load.


make -j4 SOURCES=src/mame/drivers/c64.cpp SUBTARGET=myc64

./myc6464 c64 -joy1 joy -flop ../../supersketch-Uncredited-sb168350-Page-ZimmermanSet2.d64


There's still some puzzles to figure out (like why it wants to clock in a bunch of reads from the digital joystick inputs), but at least it does something.

Re: c64 super sketch [Re: Golden Child] #115941 09/17/19 09:49 PM
Joined: Jan 2012
Posts: 1,028
rfka01 Offline
Very Senior Member
Offline
Very Senior Member
Joined: Jan 2012
Posts: 1,028
Absolutely amazing, GC! Unfortunately the Apple II disk hasn't surfaced yet.


NCR DMV- DEC Rainbow- Siemens PCD- ITT 3030-Oly People- Acorn A5000- Olivetti M20
Re: c64 super sketch [Re: Golden Child] #115942 09/18/19 03:56 AM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
Thanks, rfka01!

I thought I'd take a look at the atari version of super sketch, this was kinda fiddly because there's so many analog paddle inputs (8 to be exact). We're only interested in paddle 0 and 1, so figuring out which is which is a bit difficult. Also, the default analog setting is to be reversed.


If I hold down the joystick, and hit d (mapped to paddle 1 analog dec (but reversed so it's inc)) and keypad 8 (mapped to paddle 0 analog dec (but reversed so it's inc)) we can get past the initial screen. You can tell you're on the right track if you just hold down keypad 8 and joystick down and the color cycling gets very fast.

[Linked Image from i.imgur.com]

[Linked Image from i.imgur.com]

No labels for paddle analog inc/dec, which is which? It'd be awesome to have a little mini title in the driver like PORT_TITLE("PDL 0") that would show up in the UI.

[Linked Image from i.imgur.com]

Holding the joystick up direction while moving the analog inputs "picks up" the pen, if up is off, then it draws lines.

./mame64 a800 -cart1 ../../Super\ Sketch\ Graphics\ Master.rom

Re: c64 super sketch [Re: Golden Child] #115943 09/18/19 08:12 AM
Joined: May 2004
Posts: 890
D
Duke Offline
Senior Member
Offline
Senior Member
D
Joined: May 2004
Posts: 890
Originally Posted by Golden Child
No labels for paddle analog inc/dec, which is which? It'd be awesome to have a little mini title in the driver like PORT_TITLE("PDL 0") that would show up in the UI.


You can use PORT_NAME() for this.

Re: c64 super sketch [Re: Duke] #115944 09/18/19 01:33 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
Thanks, Duke! PORT_NAME works pretty well.

Tacking on PORT_NAME("PDL 0") and PORT_NAME("PDL 1") gives this:

[Linked Image from i.imgur.com]

Code
static INPUT_PORTS_START( atari_analog_paddles )
        PORT_START("analog_0")
        PORT_BIT(0xff, 0x72, IPT_PADDLE) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(1) PORT_REVERSE PORT_NAME("PDL 0")

        PORT_START("analog_1")
        PORT_BIT(0xff, 0x72, IPT_PADDLE) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(2) PORT_REVERSE PORT_NAME("PDL 1")


Too bad that MouseX or MouseY isn't working...I can add it to the port with PORT_CODE(MOUSECODE_X) and PORT_CODE(MOUSECODE_Y) and see it listed but it just doesn't work.

Re: c64 super sketch [Re: Golden Child] #115945 09/18/19 02:52 PM
Joined: Mar 2001
Posts: 16,394
R
R. Belmont Online Content
Very Senior Member
Online Content
Very Senior Member
R
Joined: Mar 2001
Posts: 16,394
Are you running with -mouse? Are the physical mouse axes assigned to the mouse?

Re: c64 super sketch [Re: R. Belmont] #115946 09/18/19 03:02 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
Beauty! Adding -mouse fixes it! Thanks, RB! (man how I struggled trying to get this to work!)


Holding up to "pick up the pen" seems to work.

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

Re: c64 super sketch [Re: Golden Child] #115947 09/18/19 03:13 PM
Joined: Mar 2001
Posts: 16,394
R
R. Belmont Online Content
Very Senior Member
Online Content
Very Senior Member
R
Joined: Mar 2001
Posts: 16,394
Great! That's also useful for -sl4 mouse on the IIe with Dazzle Draw, MousePaint, and Apple II DeskTop (or the IIc's built-in mouse interface).

Re: c64 super sketch [Re: R. Belmont] #115951 09/18/19 07:34 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
I was able to get the colecovision super sketch to get past the menu but the machine language is so alien to me (being a 6502 guy).

Seems to want to read from a shift register at $CF00.

Still a puzzle but it's doing something.

[Linked Image from i.imgur.com]

[Linked Image from i.imgur.com]

[Linked Image from i.imgur.com]

Seriously?

[Linked Image from i.imgur.com]

Re: c64 super sketch [Re: Golden Child] #115952 09/18/19 09:26 PM
Joined: Jan 2012
Posts: 1,028
rfka01 Offline
Very Senior Member
Offline
Very Senior Member
Joined: Jan 2012
Posts: 1,028
*snerk*


NCR DMV- DEC Rainbow- Siemens PCD- ITT 3030-Oly People- Acorn A5000- Olivetti M20
Re: c64 super sketch [Re: Golden Child] #115956 09/19/19 06:41 AM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
So the coleco has to read data from the super sketch at $CF00, but it has to write some data to the super sketch to setup the read, writing data to $E000.

We want 3 bytes of data from the super sketch so we load 3 into b. The data will be returned in 703A, 703B and 703C, so we put 703A in iy and call 89b3.

After returning from 89b3 we start to process the data in 703b.

[Linked Image from i.imgur.com]

at 89b3 we initialize ix and iy again (the ix is pointing to a table of 4 values to send).

The routine at 89dc actually sends the data to $e000 and returns the value in c.

ld (iy+$00),a puts the value into iy and we inc iy to advance our pointer.

After returning we add 4 to ix and go back to read the next byte. djnz decrements our b and restarts the loop.


[Linked Image from i.imgur.com]


89dc is where all the magic happens, we clock a bunch of values into $e000. There's a specific sequence for each byte we want, varying by the middle part that is pointed to in a table at 89a7.

When that's setup, we load 8 into b, clear c and a.

Now we loop 8 times: we clock a 0 to $e000. Then read CF00, getting the low bit and shifting c with SLA (shift left arithmetic). Adding a to c. Also clocking a 4 to $e000. A short delay with call 89d6. Finally we write a $0a into $e000.

[Linked Image from i.imgur.com]


The table at 89a7:

if 00 04 represents 0 and 02 06 represents 1, then we can look at this table as:

10
00
01

and we're selecting which of the 3 bytes we're going to return, x,y or buttons.

[Linked Image from i.imgur.com]

So we're getting closer...

Re: c64 super sketch [Re: Golden Child] #115958 09/19/19 08:39 AM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
Ok, let's see if we can get some proper data to it:

The sequence of bytes to E000: is 10,2,6,2,6,x,x,x,x,2,4,0,4,readCF00,0,4,readCF00,0,4,...10. So we'll reset our count when we see 10 and get the values at position 5 and 7 (5678 are x) to choose which item we return: x,y or buttons.

Code
WRITE8_MEMBER( coleco_state::supersketch_w )
{
    if (data==10) {m_supersketch_pos=0; m_supersketch_shiftpos=0;}
    else m_supersketch_pos++;
     if (m_supersketch_pos == 5)
          m_supersketch_item = (data==2) ? 1 : 0;
    else if (m_supersketch_pos ==7)
          {m_supersketch_item += ((data==2) ? 2 : 0);
           if      (m_supersketch_item==0) m_supersketch_data=m_test_joy1y->read();
           else if (m_supersketch_item==1) m_supersketch_data=m_test_joy1x->read();
           else if (m_supersketch_item==2) m_supersketch_data=m_test_bits->read()^0xff;
           }

   printf("e000 pos=%x data=%x  item=%x\n",m_supersketch_pos,data,m_supersketch_item);
}

READ8_MEMBER( coleco_state::cf00test_r )
{
        int bit = m_supersketch_data&0x80 ? 1 : 0;
        m_supersketch_data <<= 1;
        m_supersketch_shiftpos ++;  
        return bit;
}


Code
    if (m_cart->exists())
                m_maincpu->space(AS_PROGRAM).install_read_handler(0x8000, 0xffff, read8_delegate(FUNC(coleco_state::cart_r),this));

        m_maincpu->space(AS_PROGRAM).install_read_handler(0xcf00, 0xcf00, read8_delegate(FUNC(coleco_state::cf00test_r),this));
        m_maincpu->space(AS_PROGRAM).install_write_handler(0xe000, 0xe000, write8_delegate(FUNC(coleco_state::supersketch_w),this));



and then add some stuff to src/machine/coleco.cpp

Code
#define JOYSTICK_DELTA          80
#define JOYSTICK_SENSITIVITY    50
#define JOYSTICK_AUTOCENTER     80


static INPUT_PORTS_START( testbits )
        PORT_START("TEST_BITS")
        PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("BUT1")
        PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("BUT2")
        PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("BUT3")
        PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("BUT4")
        PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("BUT5")
        PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("BUT6")
        PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_NAME("BUT7")
        PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_NAME("BUT8")
        PORT_BIT( 0x00, IP_ACTIVE_LOW, IPT_UNKNOWN )

        PORT_START("TEST_analog_joystick_1_x")      /* Joystick 1 X Axis */
        PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X) PORT_NAME("TEST Joystick X")
        PORT_SENSITIVITY(JOYSTICK_SENSITIVITY)
        PORT_KEYDELTA(JOYSTICK_DELTA)
        PORT_CENTERDELTA(JOYSTICK_AUTOCENTER)
        PORT_MINMAX(0,0xff) PORT_PLAYER(1)
        PORT_CODE_DEC(KEYCODE_4_PAD)    PORT_CODE_INC(KEYCODE_6_PAD)
        PORT_CODE_DEC(JOYCODE_X_LEFT_SWITCH)    PORT_CODE_INC(JOYCODE_X_RIGHT_SWITCH)

           PORT_START("TEST_analog_joystick_1_y")      /* Joystick 1 Y Axis */
        PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y) PORT_NAME("TEST Joystick Y")
        PORT_SENSITIVITY(JOYSTICK_SENSITIVITY)
        PORT_KEYDELTA(JOYSTICK_DELTA)
        PORT_CENTERDELTA(JOYSTICK_AUTOCENTER)
        PORT_MINMAX(0,0xff) PORT_PLAYER(1)
        PORT_CODE_DEC(KEYCODE_8_PAD)    PORT_CODE_INC(KEYCODE_2_PAD)
        PORT_CODE_DEC(JOYCODE_Y_UP_SWITCH)      PORT_CODE_INC(JOYCODE_Y_UP_SWITCH)

INPUT_PORTS_END





and add our testbits ports to include

Code
   PORT_INCLUDE( sac2 )
        PORT_INCLUDE( driv1 )
        PORT_INCLUDE( driv2 )
        PORT_INCLUDE( roller )

        PORT_INCLUDE(  testbits )


and some stuff in src/mame/includes/coleco.h:
Code
                     m_driv_pedal2(*this, "DRIV_PEDAL2"),
                        m_roller_x(*this, "ROLLER_X"),
                        m_roller_y(*this, "ROLLER_Y"),
m_test_bits(*this, "TEST_BITS"),
m_test_joy1x(*this, "TEST_analog_joystick_1_x"),
m_test_joy1y(*this, "TEST_analog_joystick_1_y")

...

        DECLARE_READ8_MEMBER( cf00test_r );
        DECLARE_WRITE8_MEMBER( supersketch_w );

...

required_ioport m_test_bits;
required_ioport m_test_joy1x,m_test_joy1y;
int m_supersketch_pos,m_supersketch_data,m_supersketch_shiftpos;
int m_supersketch_item;


And now we can draw with the mouse (badly)

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

Re: c64 super sketch [Re: Golden Child] #115959 09/19/19 02:42 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
What's actually inside of the super sketch? Searching for the ti99 super sketch gave a couple of pages with nice hi-res pics of the board:

ti 99 super sketch

https://www.nightfallcrew.com/22/10/2016/ppi-super-sketch-for-texas-instruments-ti-994a/

http://www.ti99.com/ti/index.php?article118/super-sketch-personal-peripherals-inc


Big pic of board: (1600x900)

https://www.nightfallcrew.com/wp-co...ruments-ti-99-repair/20161016_122922.JPG


shows 6 chips, one big rom, a TI adc0834 analog to digital converter chip, 74ls30 8 input nand , 74ls139 1 to 4 decoder. 74ls367 hex bus driver, 74hc174 flip flop.



c64 super sketch:

You can see the adc0834 chip in the plug.

https://www.nightfallcrew.com/25/04/2012/super-sketch-commodore-64-ppirushware/

I didn't see the second page of pics when I first looked that show the insides of the unit:

https://www.nightfallcrew.com/25/04/2012/super-sketch-commodore-64-ppirushware/?nggpage=2


Re: c64 super sketch [Re: Golden Child] #115967 09/20/19 11:33 AM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
So let's have a look at the TI99 version of the super sketch.

The TMS9900 has really different machine language..so strange and cryptic. A for add. B for branch. BL for branch and link, this calls a subroutine putting the return address into R11, then do a b *r11 to return from the subroutine.

The wackiest thing is SOC which means Set Ones Corresponding. What does that mean? Oh it's just OR with a abstruse name. Why not just say OR? Theres an ORI or immediate in the instruction set, so it's confusing. So what does AND? SZC. SZC is set zeroes corresponding. SZC=AND, SOC=OR.


After fruitlessly staring at the code for awhile and getting familiar with the TI memory map, I had an insight, why not put a watchpoint for writes in the cart address space?

wp 6000,2000,w

and it stops writing 5050 to 0007FF0 (PC=6AAA)

Aha! That's our access to the super sketch.


Code
> wp 6000,2000,w
Watchpoint 1 set
Stopped at watchpoint 1 writing 5050 to 00007FF0 (PC=6AAA)
>wp 7ff0,1,r
Watchpoint 2 set
Stopped at watchpoint 2 reading 8080 from 00007FF0 (PC=6AB0)
Stopped at watchpoint 1 writing 4040 to 00007FF0 (PC=6AB0)

....


write pattern is 50 40 60 40 60 40 60 00 20 00 20 00 20

---- first real "read" from 7ff0

Stopped at watchpoint 2 reading 8080 from 00007FF0 (PC=6AEA)


Code
   WRITE 7ff0                  pc=6AAA  wpaddr=7FF0 wpdata=5050
   WRITE 7ff0                  pc=6AB0  wpaddr=7FF0 wpdata=4040
   WRITE 7ff0                  pc=6AB4  wpaddr=7FF0 wpdata=6060
   WRITE 7ff0                  pc=6AB8  wpaddr=7FF0 wpdata=4040
   WRITE 7ff0                  pc=6ABC  wpaddr=7FF0 wpdata=6060
   WRITE 7ff0                  pc=6AC2  wpaddr=7FF0 wpdata=4040
   WRITE 7ff0                  pc=6AC6  wpaddr=7FF0 wpdata=6060
   WRITE 7ff0                  pc=6ACA  wpaddr=7FF0 wpdata=0
   WRITE 7ff0                  pc=6ACE  wpaddr=7FF0 wpdata=2020
   WRITE 7ff0                  pc=6AD2  wpaddr=7FF0 wpdata=0
   WRITE 7ff0                  pc=6AD6  wpaddr=7FF0 wpdata=2020
   WRITE 7ff0                  pc=6AE2  wpaddr=7FF0 wpdata=0
   WRITE 7ff0                  pc=6AE8  wpaddr=7FF0 wpdata=2020
READ 7ff0  R8=0 PC=6AEA wpaddr=7FF0 wpdata=8080
   WRITE 7ff0                  pc=6AE2  wpaddr=7FF0 wpdata=0
   WRITE 7ff0                  pc=6AE8  wpaddr=7FF0 wpdata=2020
READ 7ff0  R8=0 PC=6AEA wpaddr=7FF0 wpdata=8080
   WRITE 7ff0                  pc=6AE2  wpaddr=7FF0 wpdata=0
   WRITE 7ff0                  pc=6AE8  wpaddr=7FF0 wpdata=2020
READ 7ff0  R8=0 PC=6AEA wpaddr=7FF0 wpdata=8080
   WRITE 7ff0                  pc=6AE2  wpaddr=7FF0 wpdata=0
   WRITE 7ff0                  pc=6AE8  wpaddr=7FF0 wpdata=2020
READ 7ff0  R8=0 PC=6AEA wpaddr=7FF0 wpdata=8080
   WRITE 7ff0                  pc=6AE2  wpaddr=7FF0 wpdata=0
   WRITE 7ff0                  pc=6AE8  wpaddr=7FF0 wpdata=2020
READ 7ff0  R8=0 PC=6AEA wpaddr=7FF0 wpdata=8080
   WRITE 7ff0                  pc=6AE2  wpaddr=7FF0 wpdata=0
   WRITE 7ff0                  pc=6AE8  wpaddr=7FF0 wpdata=2020
READ 7ff0  R8=0 PC=6AEA wpaddr=7FF0 wpdata=8080
   WRITE 7ff0                  pc=6AE2  wpaddr=7FF0 wpdata=0
   WRITE 7ff0                  pc=6AE8  wpaddr=7FF0 wpdata=2020
READ 7ff0  R8=0 PC=6AEA wpaddr=7FF0 wpdata=8080
   WRITE 7ff0                  pc=6AE2  wpaddr=7FF0 wpdata=0
   WRITE 7ff0                  pc=6AE8  wpaddr=7FF0 wpdata=2020
READ 7ff0  R8=0 PC=6AEA wpaddr=7FF0 wpdata=8080
   WRITE 7ff0                  pc=6B02  wpaddr=7FF0 wpdata=5050



R2 = 7FF0 (pointer to supersketch port)

Code
6A9E: CE8B      mov  R11,*R10+      r10 is our "stack" pointer, save the return address
6AA0: 0200 5050 li   R0,>5050       load immediate r0=5050  (registers are 16 bit but we're only interested in bytes so think "50")
6AA4: 0205 2020 li   R5,>2020       load immediate r5=2020
6AA8: C480      mov  R0,*R2          write 50 to 7ff0   (actually writes 5050 to 7ff0, 7ff1 gets written too but it doesn't hurt anything)
6AAA: 0200 4040 li   R0,>4040      load immediate r0=4040
6AAE: C480      mov  R0,*R2      write 40 to 7ff0
6AB0: A005      a    R5,R0          add, r0= r0 + r5   (in this case r0=6060 (4040+2020)
6AB2: C480      mov  R0,*R2      write 20 to 7ff0
6AB4: 6005      s    R5,R0           subtract, r0 = r0 + r5   (r0 = 2020 (6060-2020))
6AB6: C480      mov  R0,*R2
6AB8: A005      a    R5,R0           add r5 to r0
6ABA: C480      mov  R0,*R2         send r0 to supersketch
6ABC: 6005      s    R5,R0           subtract r5 from r0

6ABE: A036      a    *R6+,R0       add to r0 what r6 is pointing to and increment r6 by 2  (our table at 6b06)
6AC0: C480      mov  R0,*R2
6AC2: A005      a    R5,R0
6AC4: C480      mov  R0,*R2
6AC6: 6036      s    *R6+,R0        subtract from r0 what r6 is pointing at and increment by 2
6AC8: C480      mov  R0,*R2

6ACA: A005      a    R5,R0
6ACC: C480      mov  R0,*R2
6ACE: 6005      s    R5,R0
6AD0: C480      mov  R0,*R2
6AD2: A005      a    R5,R0
6AD4: C480      mov  R0,*R2
6AD6: 0209 0008 li   R9,>0008         bit counter, put 8 into r9
6ADA: 04C1      clr  R1                      clear r1
6ADC: 0A11      sla  R1,1         shift r1 left by 1 bit
6ADE: 6005      s    R5,R0 
6AE0: C480      mov  R0,*R2
6AE2: 1000      jmp  >6ae4         jumps to the next instruction
6AE4: A005      a    R5,R0
6AE6: C480      mov  R0,*R2
6AE8: C0D2      mov  *R2,R3             read data from the super sketch port (7ff0) put into r3
6AEA: 0243 8080 andi R3,>8080      and r3 with 80 (get high bit)
6AEE: 0973      srl  R3,7          shift r3 right by 7 bits (make it the low bit)
6AF0: E043      soc  R3,R1     OR r3 with r1, r1=r1 OR r3
6AF2: 0609      dec  R9           decrement our bit counter
6AF4: 16F3      jne  >6adc       go get another bit
6AF6: 06C1      swpb R1
6AF8: DA01 8382 movb R1,@>8382(R8)    store whole byte into address 8382+R8
6AFC: 0200 5050 li   R0,>5050
6B00: C480      mov  R0,*R2       write out 50 to 7ff0    (starts with a 50, ends with a 50)
6B02: 0460 6A8E b    @>6a8e




TMS9900 is really different, but once you know what you're looking at it's not so bad, the notation is funky.



[Linked Image from i.imgur.com]

Small table at 6b06:

[Linked Image from i.imgur.com]


I also figured out that it puts the buttons into 8392 to 8395,

so if you type this from the debugger:

g 6a40
g 6a8e
w@8392=0;w@8394=ff00

you can get past the title screen where it wants a menu button press.

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

Re: c64 super sketch [Re: Golden Child] #115968 09/20/19 11:43 AM
Joined: Mar 2001
Posts: 16,394
R
R. Belmont Online Content
Very Senior Member
Online Content
Very Senior Member
R
Joined: Mar 2001
Posts: 16,394
That's an EEPROM-style serial interface. 0x20 is the clock line, 0x10 is /enable (the / means enabled when low), and 0x40 is write data. So it sends 111000 to the chip then expects 8 bits of read back.

Re: c64 super sketch [Re: R. Belmont] #115970 09/20/19 06:37 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
Yes, that sounds right.

http://www.ti.com/product/ADC0834-N

[Linked Image from i.imgur.com]


A few horrible hacks later (made more difficult because the TI wants to read the address for every write to the address, and it wants to read and write in 2 byte chunks so that means 2 calls to the read and write routine).

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

Re: c64 super sketch [Re: Golden Child] #115971 09/20/19 07:35 PM
Joined: Mar 2001
Posts: 16,394
R
R. Belmont Online Content
Very Senior Member
Online Content
Very Senior Member
R
Joined: Mar 2001
Posts: 16,394
We have an ADC0834 device in src/devices/machine/adc083x.h, incidentally.

Re: c64 super sketch [Re: R. Belmont] #115975 09/21/19 03:03 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
Thanks for the pointer, RB! I did actually do a find src -name '*adc0834*' but that was too specific.

I needed to do

find src -name '*adc083*'
or
grep adc083 src -r


One of the things that's been perplexing is how the supersketch reads the buttons. There's 4 buttons (actually 3 since the lift button is repeated on each side). It has resistors on each button line so it actually reads it as an analog value from the adc0834.

That's why it has an adc0834 on the c64 when it actually reads the pad's x/y values with the potentiometer inputs on the gameport. It still uses the adc0834 to read the buttons as an analog value.

If you look closely at the nightfallcrew pictures, there's a resistor hiding under there crimped on. On the other side of the crimp that must be a resistor too. There must be at least a few more, I guess you'd need 6 for a resistor ladder?

[Linked Image from i.imgur.com]

Re: c64 super sketch [Re: Golden Child] #115979 09/21/19 10:14 PM
Joined: Jan 2018
Posts: 1
Z
zino Offline
Member
Offline
Member
Z
Joined: Jan 2018
Posts: 1
git-grep is nice and fast. Try "git grep adc0834"

Re: c64 super sketch [Re: Golden Child] #116071 10/03/19 02:15 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
Ok, let's see if we can hook up the adc0834 device (using the ksys573 driver as a guide):


add some stuff to src/drivers/mame/ti99_4x.cpp:
Code
m_test_buttons(*this, "TEST_BUTTONS"),
m_test_joy1x(*this, "TEST_ANALOG_JOYSTICK_1_X"),
m_test_joy1y(*this, "TEST_ANALOG_JOYSTICK_1_Y"),
m_adc0834(*this, "adc0834"),
m_supersketch_out0(*this, "SUPERSKETCH_OUT0"),
m_supersketch_in0(*this, "SUPERSKETCH_IN0")


double supersketch_inputs_callback(uint8_t input);

required_ioport m_test_buttons,m_test_joy1x,m_test_joy1y;
required_device<adc0834_device> m_adc0834;
required_ioport m_supersketch_out0,m_supersketch_in0;



void ti99_4x_state::memmap(address_map &map)
 {
        map.global_mask(0xffff);
        map(0x0000, 0xffff).rw(TI99_DATAMUX_TAG, FUNC(bus::ti99::internal::datamux_device::read), FUNC(bus::ti99::internal::datamux_device::write));
        map(0x7ff0, 0x7ff1).portr("SUPERSKETCH_IN0").portw("SUPERSKETCH_OUT0");
 }



make a callback for adc0834:
Code

double ti99_4x_state::supersketch_inputs_callback(uint8_t input)
{
//     printf("read adc0834 callback %x\n",input);
        switch( input )
        {
        case ADC083X_CH0:
               return m_test_joy1y->read();
        case ADC083X_CH1:
               return m_test_joy1x->read();
        case ADC083X_CH2:
               return m_test_buttons->read() ^ 0xff;
        case ADC083X_CH3:
        case ADC083X_CH4:
        case ADC083X_CH5:
        case ADC083X_COM:
                return 0;
        case ADC083X_VREF:
                return 255;
        case ADC083X_AGND:
               return 0;
        }
        return 0;  // ground
}



setup the adc0834 in the ti99_4a state:


Code
void ti99_4x_state::ti99_4a(machine_config& config)
{

...

        adc0834_device &adc(ADC0834(config, "adc0834"));
        adc.set_input_callback(FUNC(ti99_4x_state::supersketch_inputs_callback));

 }
 



and setup our ports:

keypad 6,7,8 are "LIFT", "SELECT", "MENU"

(make sure you map keypad 6 on the analog input to something else, or your analog input will jump when you hit the lift button)

Code
static INPUT_PORTS_START(ti99_4a)

        PORT_START( "SUPERSKETCH_OUT0" )
        PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER( "adc0834", adc083x_device, cs_write )  PORT_NAME("CS")
        PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER( "adc0834", adc083x_device, clk_write )  PORT_NAME("CLK")
        PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER( "adc0834", adc083x_device, di_write )   PORT_NAME("DI")

        PORT_START( "SUPERSKETCH_IN0" )
        PORT_BIT( 0x80 , IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER( "adc0834", adc083x_device, do_read )





#define JOYSTICK_DELTA          80
#define JOYSTICK_SENSITIVITY    50
#define JOYSTICK_AUTOCENTER     80


        PORT_START("TEST_BUTTONS")
        PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("BUT1") PORT_CODE(KEYCODE_1_PAD)
        PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("BUT2") PORT_CODE(KEYCODE_2_PAD)
        PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("BUT3") PORT_CODE(KEYCODE_3_PAD)
        PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("BUT4") PORT_CODE(KEYCODE_4_PAD)
        PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("BUT5") PORT_CODE(KEYCODE_5_PAD)
        PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("BUT6") PORT_CODE(KEYCODE_6_PAD)
        PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_NAME("BUT7") PORT_CODE(KEYCODE_7_PAD)
        PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_NAME("BUT8") PORT_CODE(KEYCODE_8_PAD)
        PORT_BIT( 0x00, IP_ACTIVE_LOW, IPT_UNKNOWN )

        PORT_START("TEST_ANALOG_JOYSTICK_1_X")      /* Joystick 1 X Axis */
        PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X) PORT_NAME("TEST Joystick X")
        PORT_SENSITIVITY(JOYSTICK_SENSITIVITY)
        PORT_KEYDELTA(JOYSTICK_DELTA)
        PORT_CENTERDELTA(JOYSTICK_AUTOCENTER)
        PORT_MINMAX(0,0xff) PORT_PLAYER(1)
        PORT_CODE_DEC(KEYCODE_4_PAD)    PORT_CODE_INC(KEYCODE_6_PAD)
        PORT_CODE_DEC(JOYCODE_X_LEFT_SWITCH)    PORT_CODE_INC(JOYCODE_X_RIGHT_SWITCH)

        PORT_START("TEST_ANALOG_JOYSTICK_1_Y")      /* Joystick 1 Y Axis */
        PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y) PORT_NAME("TEST Joystick Y")
        PORT_SENSITIVITY(JOYSTICK_SENSITIVITY)
        PORT_KEYDELTA(JOYSTICK_DELTA)
        PORT_CENTERDELTA(JOYSTICK_AUTOCENTER)
        PORT_MINMAX(0,0xff) PORT_PLAYER(1)
        PORT_CODE_DEC(KEYCODE_8_PAD)    PORT_CODE_INC(KEYCODE_2_PAD)
        PORT_CODE_DEC(JOYCODE_Y_UP_SWITCH)      PORT_CODE_INC(JOYCODE_Y_UP_SWITCH)

 INPUT_PORTS_END


Re: c64 super sketch [Re: Golden Child] #116072 10/03/19 03:13 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
In searching for info about the supersketch I came across the VersaWriter which was a similar device that used an arm with two sections that would use potentiometer analog inputs to calculate the position of the tip.

These were used by Roberta Williams and Jordan Mechner in making their games.

[Linked Image from i.imgur.com]

https://www.filfre.net/2011/10/mystery-house-part-1/

https://www.museumofplay.org/blog/c...on-documents-revolution-in-game-graphics


Some nice pictures here of the apple and atari versions:

https://atariage.com/forums/topic/293821-i-have-a-versawriter-i-am-trying-to-evaluate/

And an ad for the pc version:

[Linked Image from i.imgur.com]

They had these for the Apple 2, atari, pc (that I know of). I was able to find a disk image for the Atari 800 and set out to figure how it worked.

Let's start "vestigating"


If I run the atari disk image under the 800xl driver it will hang up while trying to read the controller ports. If I hit joystick right and left quickly that will "unstick" it so that gives us some hints.



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

Analyzing it, it appears that this is reading a potentiometer input by writing to $d300 a strobe with 30, choosing the axis to read with 20 or 10, then hitting the strobe again with 30. It uses the X and Y registers to hold a 16bit value, counts until the $d300 input goes low, then returns the count in 4ffe/4fff.

Putting them side by side, the x axis gets read with 30,20,30 and then anding $d300 with $40, exiting when bit 6 clears.
The y axis gets read with 30,10,30 and then anding $d300 with $80, exiting when bit 7 clears.


Why they didn't use the potentiometer input on the atari is a bit baffling. It's got paddle inputs so why not use them?


add some various bits to a400_state:

Code
                m_mypot0(*this, "myanalog_0"),
                m_mypot1(*this, "myanalog_1")

        DECLARE_READ8_MEMBER(a800xl_d300_read);
        DECLARE_WRITE8_MEMBER(a800xl_d300_write);

double m_versatime;



Our d300 read routine:
Code

READ8_MEMBER(a400_state::a800xl_d300_read)
{
if (machine().time().as_double() > m_versatime) return 0;
return 0xff;
}

WRITE8_MEMBER(a400_state::a800xl_d300_write)
{
        if (data==0x10) { m_versatime = machine().time().as_double() + attotime::from_nsec(50000).as_double()*m_mypot0->read();}
       if (data==0x20) {  m_versatime = machine().time().as_double() + attotime::from_nsec(50000).as_double()*m_mypot1->read();}
}



Modify the address map:

Code
void a400_state::a800xl_mem(address_map &map)
{
        map(0x0000, 0xcfff).rw(FUNC(a400_state::a800xl_low_r), FUNC(a400_state::a800xl_low_w));
        map(0xd000, 0xd0ff).rw(m_gtia, FUNC(gtia_device::read), FUNC(gtia_device::write));
        map(0xd100, 0xd1ff).noprw();
        map(0xd200, 0xd2ff).rw("pokey", FUNC(pokey_device::read), FUNC(pokey_device::write));
        map(0xd300, 0xd3ff).rw(m_pia, FUNC(pia6821_device::read_alt), FUNC(pia6821_device::write_alt));
// insert our d300 read and write routine
        map(0xd300, 0xd300).rw(FUNC(a400_state::a800xl_d300_read), FUNC(a400_state::a800xl_d300_write));    
        map(0xd400, 0xd4ff).rw(m_antic, FUNC(antic_device::read), FUNC(antic_device::write));
        map(0xd500, 0xd7ff).noprw();
        map(0xd800, 0xffff).rw(FUNC(a400_state::a800xl_high_r), FUNC(a400_state::a800xl_high_w));
}


add some analog inputs:
Code
     PORT_START("myanalog_0")
        PORT_BIT(0xff, 0x74, IPT_PADDLE) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(1) PORT_NAME("myanalog_0")

        PORT_START("myanalog_1")
        PORT_BIT(0xff, 0x74, IPT_PADDLE) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0xe4) PORT_PLAYER(2) PORT_NAME("myanalog_1")



and now when you get the analog just right, you can see by moving just the x or the y axis that it will "sweep" in a circular motion.

The 1 key draws, space to turn off drawing.

[Linked Image from i.imgur.com]

Re: c64 super sketch [Re: Golden Child] #116073 10/03/19 04:48 PM
Joined: Feb 2004
Posts: 2,095
Vas Crabb Offline
Very Senior Member
Offline
Very Senior Member
Joined: Feb 2004
Posts: 2,095
If you're going to emulate that device, you should have the option for MAME to do the inverse kinematic transform for you so X/Y work intuitively. It's not too difficult in two dimensions.

Re: c64 super sketch [Re: Golden Child] #116075 10/03/19 07:58 PM
Joined: Mar 2006
Posts: 1,035
L
Lord Nightmare Offline
Very Senior Member
Offline
Very Senior Member
L
Joined: Mar 2006
Posts: 1,035
Originally Posted by Golden Child

...
Why they didn't use the potentiometer input on the atari is a bit baffling. It's got paddle inputs so why not use them?
...


My guess is because of the infamous 'pokey bug':
As I understand it, the pokey ADC works by slowly charging the analog input pin via an on-die(?) resistor, and incrementing(?) an 8 bit counter until the voltage read from the pin hits a threshold, then stopping the counter, dumping the pin back to ground via a transistor, waiting a bit, then resetting the register to zero(?) and repeating.

if you read from the ADC input register while it is still counting up, you will read a bogus/invalid value, and there's no way to tell whether you're reading it in one of the 'bad' states or not. Most games which used the Pokey analog inputs worked around this by reading the ADC 3 or 5 times and 'voting' on which values were valid by majority.

The 1983 star wars arcade game famously still does this on its analog inputs even though the programmers got frustrated enough with the pokey analog reading that they switched to using dedicated analog devices ADC chips instead! They left the input voting/smoothing code in there and active by accident!

The commodore SID doesn't have this issue, since it uses two separate registers (really a counter and an 8 bit latch) for reading the analog/paddle inputs, and latches the value when the voltage threshold is reached, so the register never reads as invalid garbage. Why Atari didn't do this on the pokey is unknown.

It is actually possible that the pokey does have a separate 8-bit adc latch, but due to some state machine screwup elsewhere it sometimes gets stuck in a transparent or otherwise bogus state.

The pokey die schematics can be found at http://www.atarimuseum.com/archives/chips/pokey.zip but I have not investigated the way the ADC actually works very deeply; the information above is based mostly on other sources (asking people on IRC, etc).

EDIT2: looking at the pot scan circuitry schematics on page C012294-3, it at least seems like my assessment was largely correct: there's an array of 8 hysteresis/level compare circuits for the 8 pot inputs, and an 8x8 array of what seem to be counters storing the current count from each of those inputs, multiplexed using a single 4 or 8 bit counter (4 bits in fast mode, 8 bits in slow mode), and no 'latch' other than the fact that 7/8ths of the time one of the other counters is being incremented.

Last edited by Lord Nightmare; 10/03/19 08:12 PM.

"When life gives you zombies... *CHA-CHIK!* ...you make zombie-ade!"
Re: c64 super sketch [Re: Golden Child] #116076 10/03/19 08:04 PM
Joined: Mar 2001
Posts: 16,394
R
R. Belmont Online Content
Very Senior Member
Online Content
Very Senior Member
R
Joined: Mar 2001
Posts: 16,394
Alternatively it's possible they wanted to use the same hardware with the same pots on all systems and the values weren't amenable to the POKEY's ADC hardware.

Re: c64 super sketch [Re: Lord Nightmare] #116109 10/05/19 07:30 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
That's an interesting story about the "Pokey bug". I guess hardware has bugs just like software.

I was thinking about how awesome the pokey chip was to have 8 channels of paddle inputs that get read in hardware every screen frame, enough so that you could have 4 analog joysticks. I'm guessing that the Atari 5200 must have used the pokey to read the analog joystick controllers since the original 5200 had 4 controller ports.

According to a post on atariage: "The XL/XE as well as the 2600 is - without any tricks - capable of reading a twin-axis analog input device with up to five buttons - closest to that in existence is the Touch Tablet with its 3 buttons. Many more digital inputs for the same two ports are possible - cf. 2600 keyboard controllers, Multijoy8 and Multijoy16 - with specially programmed software."


===

Back to the versawriter, I think I've figured out the trigonometry to do the calculation, but it'd be good to know the exact dimensions of the arms, I'm guessing somewhere between 4 and 5 inches long. I think the arm pivot must be about 1 inch from the top of the image holder. Anybody have a versawriter to do the measurements?


Atari Basic is quirky, but I managed to get it to display the contents of the VWCALDA7.VER and VWCALDA8.VER files which are the calibration values to feed to the drawing programs. There are two different sets of calibration values, one for graphics 7 and one for graphics 8, as I guess that the paddle reading takes different timing on the different modes.


[Linked Image from i.imgur.com]

The first 4 values in the file are the load address and the length of the file, the load address being $600 and the length being 8 bytes.

I try to run the calibration program with my emulated paddles and it can't seem to write to the disk properly, giving me an error #138 (device not ready).


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

It pokes the values into memory at $600 so let's just save them out with the debugger command "save cal.bin,600,8" , and after loading the drawing program with

RUN "D:VWSOFTG8.BAS

or

RUN "D:VW

then loading the calibration data with "load cal.bin,600"

[Linked Image from i.imgur.com]


So far I can make it do this:

[Linked Image from i.imgur.com]

This is moving up and down and left and right with the mouse. It's not perfect, a little bit wiggly, but we're getting closer.


BTW what is the BACKSLASH2 key? That's what the atari driver maps to backspace by default. Somewhere I read that's a key on international keyboards, something about oem_102?. After making do without the backspace key for awhile, I finally mapped it to the "real" backspace key.


While searching around for atari keyboard layouts I came across this layout, it's so pretty. One day it'd be awesome if mame could have an onscreen keyboard that looks like this.

[Linked Image from i.imgur.com]

https://www.keyboard-design.com/layouts/60/Atari-800.html

Re: c64 super sketch [Re: Golden Child] #116122 10/06/19 09:26 PM
Joined: May 2004
Posts: 890
D
Duke Offline
Senior Member
Offline
Senior Member
D
Joined: May 2004
Posts: 890
BACKSLASH2 is the key to the left of the Z key:

[Linked Image from kbd-intl.narod.ru]

Re: c64 super sketch [Re: Golden Child] #116123 10/06/19 09:27 PM
Joined: Mar 2001
Posts: 16,394
R
R. Belmont Online Content
Very Senior Member
Online Content
Very Senior Member
R
Joined: Mar 2001
Posts: 16,394
Right. BACKSLASH2 doesn't exist on US-ANSI keyboards, so mapping things to it is as much of a mistake as my trying to use LWIN.

Re: c64 super sketch [Re: Golden Child] #116188 10/16/19 07:35 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
So let's figure out how do get an Atari 800 screendump so we can really study VWCALSFT.BAS. There doesn't seem to be a printer for the Atari 800 driver, so we'll just do LIST and then pause the listing by toggling CTRL+1.

A little lua script for screendump:

Code
function ram(adr) return emu.item(manager:machine().devices[":ram"].items["0/m_pointer"]):read(adr) end
function between(c,a,b) return a<=c and c<=b end
function boffset(x,y) return y*40+x end
function scrascii(c) c=c&0x7f 
   if between(c,0,0x3f) then return c+0x20 end 
   if c==0x7f then return 32 end 
   if between(c,0x60,0x7f) then return c end 
   if between (c,0x40,0x5f) then return string.byte("*") end 
end
function scrdump(startcol) startcol = startcol or 2 for y=0,23 do for x=startcol,39 do io.write (string.char(scrascii(ram(boffset(x,y)+ram(88)+ram(89)*256)))) end print () end end

-- a little test of our screendump
emu.keypost([[100 PRINT CHR$(125):FOR I=0 TO 5:PRINT:NEXT I:FOR I=0 TO 255:POKE I+PEEK(88)+PEEK(89)*256,I:NEXT I
   RUN
]])
scrdump(0)


With a little bit of stitching we get a nice listing, though CHR$(125) doesn't come through so that was added manually.

Code
READY                                 
LOAD "D:VWCALSFT.BAS                  
                                        
READY                                 
LIST                                  
                                        
                                                       
100 GRAPHICS 8:POKE 752,1             
110 DIM P8(8),P7(8),FS$(16),IO$(1)    
120 N127=127:N947=947                 
130 LGTHL=8:LGTHH=0:AUX2=0            
140 FS$="D:VWPDIV03.VER":AUX1=4:PTGT=7:GOSUB 30500                          
200 POKE 54018,56:POKE 54016,48:POKE 54018,60                               
430 POKE 20245,N0:POKE 20254,N0:POKE 20262,N0:POKE 20268,N0:POKE 20303,N0:POKE 20312,N0                           
440 POKE 20320,N0:POKE 20326,N0       
2000 BS=1:POKE 764,255                
2100 PRINT CHR$(125);                       
2105 IF BS>=5 THEN 3000               
2110 PRINT "POSITION ARMS AS SHOWN IN DIAGRAM ";BS                          
2120 PRINT "PADDLE(0)=         PADDLE(1)=  "                                
2125 PRINT :PRINT "PRESS SPACE BAR WHEN READY";                             
2130 BS=BS+1                          
2140 GRAPHICS 8+32:POKE 752,1:SETCOLOR 2,0,0                                
2150 GOSUB 6000                       
2160 P8(BS-2)=P0:P8(BS+2)=P1          
2170 GRAPHICS 7+32:POKE 752,1:SETCOLOR 2,0,0                                
2180 GOSUB 6000                       
2190 P7(BS-2)=P0:P7(BS+2)=P1          
2200 POKE 656,1:POKE 657,12:PRINT P0;"   ";:POKE 657,31:PRINT P1;"   ";     
2210 IF PEEK(764)=255 THEN 2140       
2220 POKE 764,255                     
2300 PRINT CHR$(125):FOR WT=1 TO 130:NEXT WT:GOTO 2100                            
3000 PRINT CHR$(125);"CALIBRATION IS COMPLETE ":TRAP 5500                         
3010 A=P8(0):B=P8(1):FLG=0:GOSUB 5000 
3020 POKE 1536,SL:POKE 1537,SH:POKE 1538,OL:POKE 1539,OH                    
3030 A=P8(6):B=P8(7):FLG=1:GOSUB 5000 
3050 POKE 1540,SL:POKE 1541,SH:POKE 1542,OL:POKE 1543,OH                    
3060 FS$="D:VWCALDA8.VER":ADDL=0:ADDH=6:AUX1=8:PTGT=11:GOSUB 30500          
3100 A=P7(0):B=P7(1):FLG=0:GOSUB 5000 
3120 POKE 1536,SL:POKE 1537,SH:POKE 1538,OL:POKE 1539,OH                    
3130 A=P7(6):B=P7(7):FLG=1:GOSUB 5000 
3150 POKE 1540,SL:POKE 1541,SH:POKE 1542,OL:POKE 1543,OH                    
3160 FS$="D:VWCALDA7.VER":ADDL=0:ADDH=6:AUX1=8:PTGT=11:GOSUB 30500          
3600 TRAP 40000:RUN "D:VW"            
3610 END                              
5000 IF A>=B THEN POP :GOTO 5500      
5050 S0=8192/(B-A)                    
5060 IF FLG=1 THEN O0=S0*B:GOTO 5100  
5070 O0=16384+S0*B                    
5100 SH=INT(S0)                       
5110 SL=INT((S0-SH)*256+0.5)          
5120 OV=INT(O0+0.5)                   
5130 OH=INT(OV/256)                   
5140 OL=OV-OH*256                     
5200 RETURN                           
5500 GRAPHICS 0:PRINT "ERROR IN ARM PLACEMENT----"                          
5510 PRINT "PLEASE REVIEW THE INSTRUCTIONS AND"                             
5520 PRINT "THEN REBOOT THE DISK TO TRY AGAIN."                             
5530 PRINT :END                       
6000 W=USR(20224)                     
6010 P0=PEEK(20478)+256*PEEK(20479)   
6020 W=USR(20228)                     
6030 P1=PEEK(20478)+256*PEEK(20479)   
6040 RETURN                           
30500 FOR X=1 TO LEN(FS$):POKE 1599+X,ASC(FS$(X,X)):NEXT X                  
30600 POKE 1616,AUX1:POKE 1617,AUX2:POKE 1618,PTGT                          
30605 POKE 1408,ADDL:POKE 1409,ADDH:POKE 1410,LGTHL:POKE 1411,LGTHH         
30610 M=USR(1624):IF PEEK(N947)>N127 THEN 30900                             
30630 M=USR(1627):IF PEEK(N947)>N127 THEN 30900                             
30635 M=USR(1630):IF PEEK(N947)>N127 THEN 30900                             
30640 M=USR(1633):IF PEEK(N947)>N127 THEN 30900                             
30650 RETURN                          
30900 TEMP=PEEK(N947):M=USR(1633)     
30910 GRAPHICS 0:PRINT "I/O ERROR # ";TEMP:POP                              
30920 IF TEMP<>167 THEN 30960         
30930 PRINT "HAVE YOU LOCKED 'VWCALDA8.VER' AND "                           
30940 PRINT "'VWCALDA7.VER?"          
30950 PRINT "PLEASE UNLOCK AND REBOOT THE DISK":END                         
30960 PRINT "REBOOT THE DISK WHEN THE PROBLEM"                              
30970 PRINT "IS RESOLVED."            
30980 END                             
                                      
READY                                 



We read the paddles under two different graphics modes, graphic mode 8 and graphic mode 7.
The 32 is added to not clear the screen (probably to speeds up the switching).

Coming in BS starts at 2, and gets incremented on each pass.

The BS-2 and BS+2 indexes put paddle0 values in indexes 0 to 3, and paddle1 values in indexes 4 to 7.

Diagram 1 : P8(0)=paddle0 P8(4)=paddle1
Diagram 2 : P8(1)=paddle0 P8(5)=paddle1
Diagram 3 : P8(2)=paddle0 P8(6)=paddle1
Diagram 4 : P8(3)=paddle0 P8(7)=paddle1

The P8 array is filled out while under graphics 8 mode.
The P7 array is filled out while under graphics 7 mode.

Code
2140 GRAPHICS 8+32:POKE 752,1:SETCOLOR 2,0,0                                
2150 GOSUB 6000                       
2160 P8(BS-2)=P0:P8(BS+2)=P1          
2170 GRAPHICS 7+32:POKE 752,1:SETCOLOR 2,0,0                                
2180 GOSUB 6000                       
2190 P7(BS-2)=P0:P7(BS+2)=P1     


gosub 6000 is our routine to read paddle0 and paddle1,
$4f00=20224 to read paddle0 and $4f04=20228 to read paddle1, returning the 16 bit paddle values in $4ffe and $4fff (20478 and 20479)

Code
6000 W=USR(20224)                                           
6010 P0=PEEK(20478)+256*PEEK(20479)   
6020 W=USR(20228)                     
6030 P1=PEEK(20478)+256*PEEK(20479)   
6040 RETURN             


Now here's where things get calculated:
Diagram 1 and 2 serve to calibrate paddle 0.
Diagram 3 and 4 serve to calibrate paddle 1.

A gets set to paddle0 for diagram 1.
B gets set to paddle0 for diagram 2.

Then we set FLG=0 and gosub 5000 to do the heavy calculating.

Code
3010 A=P8(0):B=P8(1):FLG=0:GOSUB 5000 
3020 POKE 1536,SL:POKE 1537,SH:POKE 1538,OL:POKE 1539,OH                    

A gets set to paddle1 for diagram 3.
B gets set to paddle1 for diagram 4.
Set FLG=1 and GOSUB 5000 to do the heavy calculating.
Code
3030 A=P8(6):B=P8(7):FLG=1:GOSUB 5000 
3050 POKE 1540,SL:POKE 1541,SH:POKE 1542,OL:POKE 1543,OH                    
3060 FS$="D:VWCALDA8.VER":ADDL=0:ADDH=6:AUX1=8:PTGT=11:GOSUB 30500    


If A>=B then error out and goto 5550. B must always be greater than A or it doesn't make sense.
We calculate our scale with 8192/(B-A).
We calculate our origin with 16384 + scale * B for paddle0 or scale * B for paddle1, depending on how FLG is set.
IF FLG=1 THEN O0=S0*B
else O0=16384+S0*B.


Code
5000 IF A>=B THEN POP :GOTO 5500      
5050 S0=8192/(B-A)                    
5060 IF FLG=1 THEN O0=S0*B:GOTO 5100  
5070 O0=16384+S0*B                    
5100 SH=INT(S0)                       
5110 SL=INT((S0-SH)*256+0.5)          
5120 OV=INT(O0+0.5)                   
5130 OH=INT(OV/256)                   
5140 OL=OV-OH*256                     
5200 RETURN            
     


These calculations are done beforehand so later all we have to do is a 16bit x 16bit multiply, as the division by (B-A) is done for us (we are just multiplying by the reciprocal of (B-A)).

Re: c64 super sketch [Re: Golden Child] #116191 10/17/19 12:54 AM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
So once we have these equations, we can make a spreadsheet, and with a bit of trial and error, deduce what the original values of the paddles when it was calibrated.

The values in VWCALDA8.VER are 58,20,193,115,84,20,70,70.


[Linked Image from i.imgur.com]

We find that PDL0 was A=250 and B=655, and PDL1 was A=482 and B=885.

[Linked Image from i.imgur.com]

the formulas in the sheet:

[Linked Image from i.imgur.com]


[Linked Image from i.imgur.com]


From a cool article on the versawriter, I now know the length of the arms: 6 inches each and the dimensions of the main board: it measures 12" vertically and 13.5" horizontally.

ATARI CLASSICS Volume 2, Issue 3 / June 1993 / PAGE 26
LOOKiNG BACK: WHAT IS VERSAWRITER?
GARY MATTESON AC STAFF REVIEWER

https://www.atarimagazines.com/atariclassics/v2n3/looking_back.php

Re: c64 super sketch [Re: Golden Child] #116214 10/18/19 02:36 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
Just posting my analysis of the versawriter reading routines:

PADDLE 0 computation

scale=(8192/(B-A))
origin=16384+(8192/(B-A))*B

8192 = 32 * 256

0 = 0x0000 0 * 256 = 0 degrees
8192 = 0x2000 32 * 256 = 90 degrees
16384 = 0x4000 64 * 256 = 180 degrees
24576 = 0x6000 96 * 256 = 270 degrees

take x, multiply x by scale, subtract that value from origin:
origin - scale * pdl = angle of position

origin - scale * pdl = angle

if pdl=B: 16384 + (8192/(B-A))*B - 8192/(B-A))*B = 16384 + 0 (since B-B=0) or 180 degrees

if pdl=A: 16384 + (8192/(B-A))*B - 8192/(B-A))*A = 16384 + 8192*(1) (since (B-A)/(B-A)=1) or 270 degrees

this result is the angle that arm 1 is pointing in (with angle=0 pointing right on the x axis).

PADDLE 1 computation
exactly the same but we don't add 16384 to the origin:

scale=(8192/(B-A))
origin=(8192/(B-A))*B


origin - scale * pdl = angle

if pdl=B: (8192/(B-A))*B - 8192/(B-A))*B = 8192 * 0 (since B-B=0) or 0 degrees

if pdl=A: (8192/(B-A))*B - 8192/(B-A))*A = 8192*(1) (since (B-A)/(B-A)=1) or 90 degrees



so the resulting angle direction is the angle from paddle 0 + angle from paddle 1 = direction that arm 2 is pointing.


The x and y coordinates are initialized to $4000,$4000 (one of the final steps is to divide this coordinate by 32 so this can be treated as 2.0,2.0).

x=2.0*32;y=2.0*32;

We read paddle0, take the precomputed origin value and subtract scale*pdl0. Now we have a value for angle0 and we add cos(angle0) to x and sin (angle0) to y. Our sine table is pre-multiplied by 32 and this value of 32 represents 1.0 multiplied by our arm length of 6.0 inches. (we can treat our sin/cos as "unit circle values" where each unit represents 6.0 inches).
The code to handle sin also calculates cos from the sin table by using cos theta=90-sin theta by eor the angle with #$1FFF (one's complement, effectively subtracting the angle 0-1fff from 90). All the values in the sine table are positive so we add or subtract from x or y depending on the quadrant.

Our sin table is 4096 bytes/2 bytes per entry for 2048 entries over 90 degrees.
Dividing 90 degrees / 2048 steps gives a resolution of .05 degree.

angle0 = origin0 - scale0 * pdl0;
x+=cos(angle0);y+=sin(angle0);

Paddle1 is then read, and the precomputed origin value is taken and scale*pdl1 is subtracted:
Then this angle1 is added to angle0 so we are "turning" left from the direction pointed by angle0.

angle1 = (origin1 - scale1*pdl1);
angle1 += angle0;
x+=cos(angle1);y+=sin(angle1);

The final steps are to scale our resulting x/y coordinates to screen coordinates.

We divide by 32;

x >>= 5;
y >>= 5;

Subtract 0x1ea8 from x, 0x4aa8 from y.

x-=0x1ea8; this has the effect of subtracting 0.95
y-=0x4aa8; this has the effect of subtracting 2.33

Then multiply by 0x990e and 0x7740.

x*=0x990e; this multiplies by 153.05 (153.05 * 2 = 306, very close to horizontal resolution of 320)
12 inches mapped to 306 pixels (25.5 pix/inch))
y*=0x7740; this multiplies by 119.25 (119.25 * 1.67 = 198.73, very close to vertical resolution of 192)
(119.25 * 1.33 = 159, matches visible vertical resolution of 160
with 4 text lines at the bottom
and it's 8 inches mapping to 160 pixels
(20 pix/inch))

x coordinate before subtracting 0.95 runs from (1.0 to 3.0, or 2-1 to 2+1).
y coordinate before subtracting 2.33 runs from (2.0 to 4.0, or 2,2+1+1).

x coordinate of 1.0 becomes screen x = 6
x coordinate of 3.0 becomes screen x = 312

y coordinate of 2.33 becomes screen y = 0
y coordinate of 3.67 becomes screen y = 159



The versawriter reading code at $4c00-$4dff implements 16 bit addition ($4d2e) and 16 bit subtraction ($4d1a) routines using two 16 bit "registers" at $610/611 (ACC1) and $612/613 (ACC2). $4d2e does ACC1 += ACC2, AND $4d1a does ACC1 -= ACC2;

There is a routine to do 16 bit x 16 bit multiply with a 32 bit result ($4d42), multiplicand in cf,d0, multiplier in cb,cc, with results in cb,cc,cd,ce cb=lowest byte ce=highest byte.

After writing up my routine to feed the paddle values to the versawriter code, I was still getting wacky results, which was driving me wacky, so I thought, why not make sure it's getting the correct values so I decided to just stuff the value in 4dfc/4dfd and patching the paddle read routine to just copy these values into 4dfe/4dff.

Analog reading by the versawriter routine:
[Linked Image from i.imgur.com]

Directly plugging the analog values into memory:
[Linked Image from i.imgur.com]


Lo and behold I get "perfect" straight axis lines. Something is affecting the timing of the read routine. At the beginning of the read routine, there's code to busy-wait until we are on scanline #1 (waiting for VCOUNTER=1), so that should allow the analog read to have consistent timing. Somehow this isn't working correctly. Interestingly, the variation in reading is very consistent, it tracks the exact same weird paths.

So I guess there's more mysteries to be solved.

Re: c64 super sketch [Re: Golden Child] #116215 10/18/19 02:38 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
After getting a little frustrated with the versawriter, why not try something else:

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

Re: c64 super sketch [Re: Golden Child] #116218 10/19/19 03:39 AM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
[Linked Image from i.imgur.com]

They made units compatible with atari vcs, 400/800, apple ii, c64, vic20, and ibm pc.

It only needed two input lines (data,sense) and two output lines (clock, clear).

[Linked Image from i.imgur.com]

The manual for the programming kit gives lots of technical details.

[Linked Image from i.imgur.com]

Re: c64 super sketch [Re: Golden Child] #116221 10/19/19 01:42 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358

Re: c64 super sketch [Re: Golden Child] #116222 10/19/19 02:09 PM
Joined: Mar 2001
Posts: 16,394
R
R. Belmont Online Content
Very Senior Member
Online Content
Very Senior Member
R
Joined: Mar 2001
Posts: 16,394
This would be easy to support on the A2 if the software turned up.

Re: c64 super sketch [Re: R. Belmont] #116231 10/20/19 01:40 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
Yes, I can't wait for the apple 2 stuff to show up.

Okay, here's my crap code that seems to work for microillustrator, leo's paintbrush and micromaestro.

Mangling the atari400.cpp file:

Code
// add to the a400_state initializer:

              m_mypot0(*this, "myanalog_0"),
              m_mypot1(*this, "myanalog_1"),
              m_test_buttons(*this, "TEST_BUTTONS")

// add a bunch of a400_state members:

    required_ioport m_mypot0,m_mypot1;
    required_ioport m_test_buttons;


  DECLARE_READ8_MEMBER(a800xl_d300_read);
  DECLARE_WRITE8_MEMBER(a800xl_d300_write);


int powerpad_sense;
int powerpad_clock;
int powerpad_clear;
int powerpad_clock_new;
int powerpad_clear_new;
int powerpad_shift;

int reverse_8bits(int x);


int powerpad_list_counter;
static const int powerpad_list_size=20;
int powerpad_list[powerpad_list_size][2];



// add our d300 read and write into the map

void a400_state::a800xl_mem(address_map &map)
{
        map(0x0000, 0xcfff).rw(FUNC(a400_state::a800xl_low_r), FUNC(a400_state::a800xl_low_w));
        map(0xd000, 0xd0ff).rw(m_gtia, FUNC(gtia_device::read), FUNC(gtia_device::write));
        map(0xd100, 0xd1ff).noprw();
        map(0xd200, 0xd2ff).rw("pokey", FUNC(pokey_device::read), FUNC(pokey_device::write));
        map(0xd300, 0xd3ff).rw(m_pia, FUNC(pia6821_device::read_alt), FUNC(pia6821_device::write_alt));
        map(0xd300, 0xd300).rw(FUNC(a400_state::a800xl_d300_read), FUNC(a400_state::a800xl_d300_write));   // add our d300 read and write into the map
        map(0xd400, 0xd4ff).rw(m_antic, FUNC(antic_device::read), FUNC(antic_device::write));
        map(0xd500, 0xd7ff).noprw();
        map(0xd800, 0xffff).rw(FUNC(a400_state::a800xl_high_r), FUNC(a400_state::a800xl_high_w));
}


READ8_MEMBER(a400_state::a800xl_d300_read)
{  // return two things: data bit and sense bit
int retval=((powerpad_shift & (1<<15)) ? 0 : 1) | ((powerpad_sense ? 1 : 0) << 3);
//printf("RETURN %x  %s\n",retval,machine().describe_context().c_str());
return  retval;
}

WRITE8_MEMBER(a400_state::a800xl_d300_write)
{
//printf("d300 write: %x\n",data);
powerpad_clock_new = data & (1<<2);
powerpad_clear_new = data & (1<<1);

if ((powerpad_clock_new) && (powerpad_clock == 0))  // clock going high
   {   powerpad_shift <<= 1;  // shift it one to the left
       printf("SHIFT powerpad shift=%x , %s   %s\n",powerpad_shift,std::bitset<16>(powerpad_shift).to_string().c_str(),machine().describe_context().c_str());
  }

if ((powerpad_clear_new) && (powerpad_clear==0)) // clear going high
{
   printf("CLEAR %s\n",machine().describe_context().c_str());
   powerpad_sense=0;

    // send next list point
    powerpad_list_counter--;

    if(powerpad_list_counter<0) // then we need to build a new list
    {

    //first entry is always 0,0
    powerpad_list_counter++;
    powerpad_list[powerpad_list_counter][1]= 0;
    powerpad_list[powerpad_list_counter][0]= 0;

if ( ((m_test_buttons->read()^0xff)&0x01)==0  )   // button 1 pressed is "pick up all presses"
{
    // now add the current position of our analog input (reversing it and clamping it to 0-119)
    // x coordinate gets reversed (since x grows to the left)
    // y coordinate is not reversed

    powerpad_list_counter++;
    powerpad_list[powerpad_list_counter][0]= 119-std::min((int)m_mypot0->read()&0x7f,119);
    powerpad_list[powerpad_list_counter][1]=     std::min((int)m_mypot1->read()&0x7f,119);
}

// hardcode some powerpad locations, button 2 is "pen down" for microillustrator
    if ((m_test_buttons->read()^0xff)&0x02)  // button 2 pressed
     { powerpad_list_counter++;
      powerpad_list[powerpad_list_counter][0]= 5;
      powerpad_list[powerpad_list_counter][1]= 5;
     }
    if ((m_test_buttons->read()^0xff)&0x04)  // button 3 pressed  "menu for microillustrator"
     { powerpad_list_counter++;
      powerpad_list[powerpad_list_counter][0]= 25;
      powerpad_list[powerpad_list_counter][1]= 5;
     }
    if ((m_test_buttons->read()^0xff)&0x08)  // button 4 pressed  "lock button for microillustrator"
     { powerpad_list_counter++;
      powerpad_list[powerpad_list_counter][0]= 60;
      powerpad_list[powerpad_list_counter][1]= 5;
     }
    if ((m_test_buttons->read()^0xff)&0x10)  // button 5 pressed   "rightmost note for micromaestro"
     { powerpad_list_counter++;
      powerpad_list[powerpad_list_counter][0]= 4;
      powerpad_list[powerpad_list_counter][1]= 115;
     }

    if ((m_test_buttons->read()^0xff)&0x20)  // button 6 pressed  "second to rightmost note for micromaestro"
     { powerpad_list_counter++;
      powerpad_list[powerpad_list_counter][0]= 12;
      powerpad_list[powerpad_list_counter][1]= 115;
     }

    // now lets sort our list in y major order (x first sort key y secondary sort key)
    // bubble sort is inefficient, but there's only going to be a couple of points here

   int swaps,temp;
   for (int pass=1;pass<powerpad_list_size;pass++)
  {  swaps=0;
     for (int i=1;i<powerpad_list_counter-1;i++)  
         if (  (powerpad_list[i][0] >  powerpad_list[i+1][0]) ||
               ((powerpad_list[i][0] == powerpad_list[i+1][0]) && (powerpad_list[i][1] >  powerpad_list[i+1][1]))
            ) {  swaps++;
                 temp = powerpad_list[i][0]; powerpad_list[i][0]=powerpad_list[i+1][0];powerpad_list[i+1][0]=temp;
                 temp = powerpad_list[i][1]; powerpad_list[i][1]=powerpad_list[i+1][1];powerpad_list[i+1][1]=temp;  // oops had a 0 instead of a 1
              }
      if (swaps==0) break;
   } // end bubblesort

     printf("POINT LIST SIZE=%x\n",powerpad_list_counter);
      for (int i=0;i<=powerpad_list_counter;i++) printf("POINT LIST %x: %x,%x\n",i,powerpad_list[i][0],powerpad_list[i][1]);

    }  // end building list

     powerpad_shift = 0x01<<14 |   // first two bits are 0 and 1 
                      ((reverse_8bits(powerpad_list[powerpad_list_counter][1])>>1)<<7)  |   // 7 bits of y coordinate LSB first
                      ((reverse_8bits(powerpad_list[powerpad_list_counter][0])>>1)<<0);}    // 7 bits of x coordinate LSB first

     printf("m_mypot0=%x   m_mypot1=%x ",m_mypot0->read()&0x7f,m_mypot1->read()&0x7f);
     printf("LOAD powerpad shift=%x , %s   y=%x  x=%x\n",powerpad_shift,std::bitset<16>(powerpad_shift).to_string().c_str(),reverse_8bits( ((powerpad_shift&(0x7f<<7))>>7)<<1),reverse_8bits((powerpad_shift&0x7f)<<1));

powerpad_clock = powerpad_clock_new;
powerpad_clear = powerpad_clear_new;
}



int a400_state::reverse_8bits(int x){  // little routine to reverse 8 bits
int retval=0;
for (int i=0;i<8;i++){retval |= ((x & (1 << (7-i)) ? (1 << i) : 0));}
printf("reverse bits %x %x\n", x, retval);
return retval;
}




#define JOYSTICK_DELTA          10
#define JOYSTICK_SENSITIVITY    50



        PORT_START("myanalog_0")
        PORT_BIT(0xff, 0x3c, IPT_PADDLE) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0x77) PORT_PLAYER(1) PORT_NAME("myanalog_0")

        PORT_START("myanalog_1")
        PORT_BIT(0xff, 0x3c, IPT_PADDLE) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0x00,0x77) PORT_PLAYER(2) PORT_NAME("myanalog_1")

        PORT_START("TEST_BUTTONS")
        PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("BUT1") PORT_CODE(KEYCODE_1_PAD)
        PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("BUT2") PORT_CODE(KEYCODE_2_PAD)
        PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("BUT3") PORT_CODE(KEYCODE_3_PAD)
        PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("BUT4") PORT_CODE(KEYCODE_4_PAD)
        PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("BUT5") PORT_CODE(KEYCODE_5_PAD)
        PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("BUT6") PORT_CODE(KEYCODE_6_PAD)
        PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_NAME("BUT7") PORT_CODE(KEYCODE_7_PAD)
        PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_NAME("BUT8") PORT_CODE(KEYCODE_8_PAD)
        PORT_BIT( 0x00, IP_ACTIVE_LOW, IPT_UNKNOWN )





So a couple of notes:

First, the software is supposed to read the powerpad and check for any stuck points, so you should hold down the keypad 1 until this is done (picks up the "stylus").
I've used an analog input to represent the "finger" that is pressing.

Control of the software is pretty difficult since you're just "blind" clicking on different spots with the mouse since you can't see the mylar overlay.
So what you see is what I could do with random clicking.

The micromaestro shows "multitouch" with the mouse plus holding down the 5 key.


The "insert power pad" screen is when I accidentally reversed the sense bit.


And some pictures:

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

Re: c64 super sketch [Re: Golden Child] #116233 10/20/19 03:40 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
In searching about, I did find an a2r file of Logicmaster for Apple II, but this is a huge file made by applesauce. How would I convert this to a usable disk image?

LogicMaster - Disk 1, Side A.a2r
04-Apr-2019 18:23
18.8M

Re: c64 super sketch [Re: Golden Child] #116236 10/21/19 12:01 AM
Joined: Mar 2001
Posts: 16,394
R
R. Belmont Online Content
Very Senior Member
Online Content
Very Senior Member
R
Joined: Mar 2001
Posts: 16,394
A2R can be converted to .WOZ or .DSK with the AppleSauce program, which currently only runs on a recent modern Mac.

Re: c64 super sketch [Re: R. Belmont] #116238 10/21/19 12:58 AM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
I've got an older Mac (Core 2 Duo) but that probably isn't recent enough to run AppleSauce perhaps. Would you be kind enough to convert it for me if I send you the link?

I did manage to find a .woz image of Apple II BearJam! Huzzah!

I just had a quick look and it looks pretty simple:

It looks like it hits AN0 for the clock and AN1 for the clear, and c061 for the data bit and c063 for the sense bit. Now let's see if I can get it to work.

Code
556E: D0 FD    bne $556d
5570: AD 63 C0 lda RD63
5573: 10 0C    bpl $5581
5575: 20 D7 53 jsr $53d7
5578: E8       inx
5579: D0 F0    bne $556b
557B: 20 6C 45 jsr $456c
557E: 4C 69 55 jmp $5569
5581: AD 5B C0 lda SETAN1
5584: AD 5A C0 lda CLRAN1
5587: 20 B7 55 jsr $55b7
558A: 85 12    sta $12
558C: 20 B7 55 jsr $55b7
558F: 85 13    sta $13
5591: AD 59 C0 lda SETAN0
5594: AD 58 C0 lda CLRAN0



Code
55B7: A2 07    ldx #$07
55B9: A9 00    lda #$00
55BB: 85 1F    sta $1f
55BD: AD 5B C0 lda SETAN1
55C0: AD 5A C0 lda CLRAN1
55C3: AD 61 C0 lda RDBTN0
55C6: 0A       asl a
55C7: 66 1F    ror $1f
55C9: CA       dex
55CA: D0 F1    bne $55bd
55CC: A5 1F    lda $1f
55CE: 49 FF    eor #$ff
55D0: 4A       lsr a
55D1: 60       rts

Re: c64 super sketch [Re: Golden Child] #116240 10/21/19 01:58 AM
Joined: Mar 2001
Posts: 16,394
R
R. Belmont Online Content
Very Senior Member
Online Content
Very Senior Member
R
Joined: Mar 2001
Posts: 16,394
Yeah, I can convert if you send the link.

Re: c64 super sketch [Re: R. Belmont] #116243 10/21/19 01:16 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
Thanks, RB!

Inserting my powerpad code into the Apple 2 driver allows me to get past the title screens of BearJam and LogicMaster.


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

I'm not sure if it's working correctly yet in sending the proper data but it seems to do something.

I'm going to create a list of points and "click" on the location by using a combination of 2 keypad keys (there's 16 keys on the keypad so that should let me do 8x8= 64 button locations).

Re: c64 super sketch [Re: Golden Child] #116260 10/23/19 01:50 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
Chalk Board's LogicMaster is really a lame game, but it's far more interesting to find out how it works. The game is just mastermind with card suits and colors. Personally I like the Coleco Digits game for a mastermind-type game. It'd be an interesting exercise to make a coleco digits overlay and game for the powerpad.

The overlay has got a lot of "buttons", there are 34.


[Linked Image from i.imgur.com]

So let's try to make a list of buttons to press:

Code
int powerpad_map[64][2];  // map buttons to powerpad coordinates


void apple2_state::powerpad_make_buttons(int loc,int xo,int yo, int xnum, int ynum, int xoffset, int yoffset, int xrowoffset, int yrowoffset) {

for (int y=0;y<ynum;y++){
for (int x=0;x<xnum;x++){
       powerpad_map[loc][0]=(xo +xoffset*x + xrowoffset*y);
       powerpad_map[loc][1]=(yo+ yoffset*x + yrowoffset*y);
       printf("Add button  %d  %x  at (%d,%d)\n",loc,loc,powerpad_map[loc][0],powerpad_map[loc][1]);
       powerpad_map[loc][0]*=-1;
       powerpad_map[loc][0]+=119;  // xcoordinates are reversed since x=0 is at the right
       loc++;
}
}
}


Code
static int makebuttonsflag=0;
if (!makebuttonsflag){

powerpad_make_buttons(1*8,38,62,6,1,12,0,0,0);  // 123456 
powerpad_make_buttons(2*8,45,11,2,2,12,-7,12,14);  // suits  
powerpad_make_buttons(3*8,93,5,2,3,14,8,0,16);  // colors
powerpad_make_buttons(4*8,79,105,3,2,14,-8,14,8);  // lower right
powerpad_make_buttons(5*8,56,97,1,2,14,-8,0,16);  // lower middle
powerpad_make_buttons(6*8,8,90,3,2,14,8,0,16);  // lower left
powerpad_make_buttons(7*8,8,45,2,2,14,-8,0,16);  // middle left
powerpad_make_buttons(0*8,8,15,2,1,14,-8,0,16);  // upper left

makebuttonsflag=1;
}



When running it I get a list of buttons as I make them:
Add button 8 8 at (38,62)
Add button 9 9 at (50,62)
Add button 10 a at (62,62)
Add button 11 b at (74,62)
Add button 12 c at (86,62)
Add button 13 d at (98,62)
Add button 16 10 at (45,11)
Add button 17 11 at (57,4)
Add button 18 12 at (57,25)
etc


then we can scan our button numpadkeys from 0 to 7, then 8 to 15 and if they're both pressed, issue the coordinates from our 8x8 table, ignoring it if the coordinates are 0,0.

Code
int but1,but2;
int buttonread;
int item;

for(but1=0;but1<8;but1++){
for(but2=0;but2<8;but2++){  
    buttonread=m_test_buttons->read() ^ 0xffff; 
    if ( ((buttonread) & (1<<but1)) && ((buttonread) & (1<<(but2+8))) )
     { 
     item = but1*8+but2;
     printf("item = %d   (%d,%d)\n",item,119-powerpad_map[item][0],powerpad_map[item][1]);     
     if ((powerpad_map[item][0] !=0) && (powerpad_map[item][1] !=0))
        {powerpad_list_counter++;
         powerpad_list[powerpad_list_counter][0]= powerpad_map[item][0];
         powerpad_list[powerpad_list_counter][1]= powerpad_map[item][1];
        }
     }
   }
   }




and expand our test buttons up to 16 buttons, using up all the keypad keys
Code
     PORT_START("TEST_BUTTONS")
        PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON16 ) PORT_NAME("BUT0") PORT_CODE(KEYCODE_0_PAD)
        PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("BUT1") PORT_CODE(KEYCODE_1_PAD)
        PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("BUT2") PORT_CODE(KEYCODE_2_PAD)
        PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("BUT3") PORT_CODE(KEYCODE_3_PAD)
        PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("BUT4") PORT_CODE(KEYCODE_4_PAD)
        PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("BUT5") PORT_CODE(KEYCODE_5_PAD)
        PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("BUT6") PORT_CODE(KEYCODE_6_PAD)
        PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_NAME("BUT7") PORT_CODE(KEYCODE_7_PAD)
        PORT_BIT( 0x100, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_NAME("BUT8") PORT_CODE(KEYCODE_8_PAD)
        PORT_BIT( 0x200, IP_ACTIVE_LOW, IPT_BUTTON9 ) PORT_NAME("BUT9") PORT_CODE(KEYCODE_9_PAD)
        PORT_BIT( 0x400, IP_ACTIVE_LOW, IPT_BUTTON10 ) PORT_NAME("BUTA") PORT_CODE(KEYCODE_SLASH_PAD)
        PORT_BIT( 0x800, IP_ACTIVE_LOW, IPT_BUTTON11 ) PORT_NAME("BUTB") PORT_CODE(KEYCODE_ASTERISK)
        PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON12 ) PORT_NAME("BUTC") PORT_CODE(KEYCODE_MINUS_PAD)
        PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON13 ) PORT_NAME("BUTD") PORT_CODE(KEYCODE_PLUS_PAD)
        PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON14 ) PORT_NAME("BUTE") PORT_CODE(KEYCODE_ENTER_PAD)
        PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_BUTTON15 ) PORT_NAME("BUTF") PORT_CODE(KEYCODE_DEL_PAD)



It's not easy to enter button presses with a chord keyboard but it works.

So now I can "play" a game, but something's weird with the randomization, I get the same card/suits for each item.

This game is really complicated enough that I had to read the manual to figure out what's going on, S= suits, C=colors,Sp =Suit correct position, Cp = color correct position.

Here's the game setup for 6 cards, 4 suits and 6 colors.

[Linked Image from i.imgur.com]

I guessed it correctly, 6 white hearts!

[Linked Image from i.imgur.com]

Re: c64 super sketch [Re: Golden Child] #116269 10/24/19 03:01 AM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
With some digging into the code, I was able to find the table of buttons and the code that reads them.

LogicMaster on the Apple II has a button compare routine that looks like this:

There's $22=34 different buttons and we match the coordinate given within $0a=10 units.

[Linked Image from i.imgur.com]

and the compare coordinate table is:

[Linked Image from i.imgur.com]


We have LogicMaster on the Atari 800 (which doesn't work properly for some reason, it runs, just very very slowly)

The read routine is virtually identical and the compare coordinate table is identical. The only difference is the addresses for the tablet x and y coordinates: $6a/6b for apple, $08/09 for atari.

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




Let's see them side by side:

Apple on left/Atari on right
[Linked Image from i.imgur.com][Linked Image from i.imgur.com]



Finding a .d64 of Leo's Links for the C64, the compare routine is similar, but it wants to be more exact, within 5 units. It has the x and y coords in $08/$09 like atari. This table has $23=35 different buttons.

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

[Linked Image from i.imgur.com]


The only picture of the Leo's Links overlay that I could find.

[Linked Image from i.imgur.com]

Youtube Video of Leo's links on the c64.

https://www.youtube.com/watch?v=OI-fYOtOLpw

Taped for the Commodore Vegas Expo v12 2016, Roger Van Pelt shows the Chalk Board PowerPad, a large tablet which came with optional accessory applications, like Leo's Links, Leo's Lectric Paintbrush, and MicroMaestro. Filmed by Robert Bernardo


Re: c64 super sketch [Re: Golden Child] #116270 10/24/19 11:05 AM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
So let's see if we can draw this target list on the screen:

If we pause the emulation we can "draw" on the screen:
Code
ram=emu.item(manager:machine().devices[":ram"].items["0/m_pointer"])
tablesize=ram:read(0x811d) tablex=0x8153 tabley=0x8176  boxsize=5 xmult=320/120 ymult=200/120
emu:pause() for i=0,tablesize-1 do 
x=ram:read(tablex+i) y=ram:read(tabley+i) print(i,x,y)
manager:machine().screens[":screen"]:draw_box((x)*xmult,y*ymult,(x+boxsize)*xmult,(y+boxsize)*ymult,0xc0ffffff,0xff000000) 
end 
-- emu:unpause() to get things running again

Interestingly, the x coordinates aren't reversed in the table.

[Linked Image from i.imgur.com]


For Apple II Logicmaster:

X coordinates are reversed in this table (matches the pad xcoordinates)

Code
ram=emu.item(manager:machine().devices[":ram"].items["0/m_pointer"])
emu:unpause()
emu:pause() for i=0,ram:read(0x6ef9)-1 do 
x=ram:read(0x6eb4+i) y = ram:read(0x6ed6+i) print (i,x,y) 
manager:machine().screens[":screen"]:draw_box((119-x)*2,y,(119-x-10)*2,y+10,0xc0ffffff,0xff000000) end 

[Linked Image from i.imgur.com]


Re: c64 super sketch [Re: Golden Child] #116271 10/24/19 01:46 PM
Joined: Mar 2001
Posts: 16,394
R
R. Belmont Online Content
Very Senior Member
Online Content
Very Senior Member
R
Joined: Mar 2001
Posts: 16,394
I was a bit confused what the Power Pad actually was until I saw that it uses overlays for these special-function games. Good work reverse-engineering it, I'm just fuzzy on how we'd emulate it right now smile

Re: c64 super sketch [Re: R. Belmont] #116275 10/25/19 03:32 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
Thanks, RB! (and thanks again for converting LogicMaster for me)

My plan was to create an additional screen and load in a picture of the overlay. Then draw the overlay and also a cursor based on an analog input. I've been looking at the png loading code in rendutil.cpp:


bool render_load_png(bitmap_argb32 &bitmap, emu_file &file, const char *dirname, const char *filename, bool load_as_alpha_to_existing)

and it loads the png into a bitmap_argb32 with:

if (PNGERR_NONE != png.copy_to_bitmap(bitmap, hasalpha))


The part that I'm having trouble with is how to draw this loaded bitmap_argb32 to my screen bitmap which is rgb32. They're both 32 bits, right?

Re: c64 super sketch [Re: Golden Child] #116276 10/25/19 03:37 PM
Joined: May 2009
Posts: 1,822
J
Just Desserts Offline
Very Senior Member
Offline
Very Senior Member
J
Joined: May 2009
Posts: 1,822
They're both 32 bits. Just write each pixel as 0xff000000 | srcbitmap.pix32(y, x); or whatever.

Re: c64 super sketch [Re: Just Desserts] #116279 10/26/19 12:55 AM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
Thanks for your suggestion, JD. It works a treat.

I hacked up a little code (copied from render_load_png) to read a png called "LogicMasterMylar.png" which I resized to 560 pixel width and loaded that into a 560x384 screen that matched the size of the apple 2 screen.


Code

//adding a powerpad_bitmap member:

bitmap_argb32 powerpad_bitmap;  // not a bitmap_rgb32


int32_t apple2_state::screen_update_powerpad(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{

if (!powerpad_bitmap.valid())      
{
        const char * filename="LogicMasterMylar.png";

        emu_file file("",OPEN_FLAG_READ);;
        osd_file::error const filerr = file.open(filename);
        if (filerr != osd_file::error::NONE)
                {printf("no file!"); return 0;}

        // read the PNG data
        png_info png;
        png_error const result = png.read_file(file);
        file.close();
        if (result != PNGERR_NONE)
        {
                osd_printf_error("%s: Error reading PNG file\n", filename);
                return 0;
        }
      bool hasalpha=false;
      if (PNGERR_NONE != png.copy_to_bitmap(powerpad_bitmap, hasalpha))
                {
                        osd_printf_error("%s: Error copying PNG bitmap to MAME bitmap\n", filename);
                        return false;
                }
printf("powerpad bitmap size %d %d\n",powerpad_bitmap.width(),powerpad_bitmap.height());
printf("screen bitmap size %d %d\n",bitmap.width(),bitmap.height());
}

for (int x=0;x<bitmap.width();x++)
for (int y=0;y<bitmap.height();y++) 
      bitmap.pix32(y,x)=powerpad_bitmap.pix32(y,x);
  
return 0;
}

Yes, I need to probably resize the graphic to fit, but I was so happy to see it load a png for the first time.

[Linked Image from i.imgur.com]

Re: c64 super sketch [Re: Golden Child] #116280 10/26/19 10:14 AM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
Since I can read pngs now why not have a hand graphic.

Now I've got a "hand" pointer that moves around by reading the analog inputs, drawing it with alpha=128.

Since the original mylar images were roughly 900x900 why not just go with 900x900.

[Linked Image from i.imgur.com]


Code
powerpad_handx = m_mypot0->read()*(900/120.0);
powerpad_handy = m_mypot1->read()*(900/120.0);

int xo=powerpad_handx-fingertipx;
int yo=powerpad_handy-fingertipy;

for (int x=xo;x<xo+powerpad_hand_bitmap.width();x++)
for (int y=yo;y<yo+powerpad_hand_bitmap.height();y++)
      if ((x>=0) && (x<bitmap.width()) && (y>=0) && (y<bitmap.height())) 
           bitmap.pix32(y,x)=alpha_blend_r32(bitmap.pix32(y,x),powerpad_hand_bitmap.pix32(y-yo,x-xo),0x80);




It's sooooo much easier to play using a mouse than my wacky chord keyboard. There's still something weird about the complete lack of randomization.

[Linked Image from i.imgur.com]

If I overlay the buttons, they're pretty close to the graphics.

Code
emu:unpause()
ram=emu.item(manager:machine().devices[":ram"].items["0/m_pointer"])
emu.pause() for i=0,ram:read(0x6ef9)-1 do x=ram:read(0x6eb4+i) y = ram:read(0x6ed6+i) print (i,x,y) manager:machine().screens[":powerpad_screen"]:draw_box((119-x)*(900/120),y*(900/120),(119-x-10)*(900/120),(y+10)*(900/120),0xc0ffffff,0xff000000) end

[Linked Image from i.imgur.com]

Re: c64 super sketch [Re: Golden Child] #116288 10/26/19 06:00 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
It's interesting what you find when searching for information on the PowerPad and ChalkBoard.

I was able to find out the author of the software: Richard Ben Satterfield and discover that the Powerpad had a life after ChalkBoard, where it was sold by Dunamis, inc for Assistive Technology (AT) Applications.

from Ben Satterfield's CV:

Software Design:

Educational designer and team leader for development of these products:
• BearJam (1983) © Chalkboard, Inc.
• LogicMaster (1983) © Chalkboard, Inc.
• PowerPad Programming Kit (1983) © Chalkboard, Inc.
• Leo’s Links (1984) © Chalkboard, Inc.
• SimpleCom I (1985) © Dunamis, Inc.
• SimpleCom II (1986) © Dunamis, Inc.
• Powerpad ToolKit (1990) © Dunamis, Inc.



searching google on "dunamis powerpad" gets some interesting hits:

https://www.simcobox.com/blog/60/

Simco is "Standard Injection Molding Co" who injection molded the interface modules.

There was actually an interface that connected the Powerpad to a Macintosh.

[Linked Image from i.imgur.com]



According to another article that there were at least 75,000 Powerpads. It was used in a project called Power Art which used a mac and hyperstudio 2.0.

[Linked Image from i.imgur.com]

https://books.google.com/books?id=D...p;lpg=RA1-PA22&dq=power+art+powerpad

Re: c64 super sketch [Re: Golden Child] #116289 10/26/19 06:34 PM
Joined: Mar 2013
Posts: 307
I
ICEknight Online Happy
Senior Member
Online Happy
Senior Member
I
Joined: Mar 2013
Posts: 307
Originally Posted by Golden Child
[Linked Image from i.imgur.com]

Will there be a way to un-squash the buttons view so that the original proportions will be displayed?


LCD artwork scans and cleanups: https://mega.nz/#F!uFYSzK7S!U-lJon9jsqyoCX_3y7_KLA
Re: c64 super sketch [Re: ICEknight] #116290 10/26/19 07:16 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
The simplest thing I could think of was to load up mame with -window -numscreens 2 and then go into the video options and choose screen 1 pixel aspect 1:1

[Linked Image from i.imgur.com]

Re: c64 super sketch [Re: Golden Child] #116291 10/27/19 01:52 AM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
another thing I haven't tried yet is perhaps setting the screen aspect with screen.set_physical_aspect(3,3)

Re: c64 super sketch [Re: Golden Child] #116292 10/27/19 02:45 AM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
In doing research on the Powerpad, it's made me interested in all kinds of AT (Assistive Technology) stuff and I've been reading up on the Adaptive Firmware Card for the Apple II.

https://resna.stanford.edu/TopTen/index.htm#1
[Linked Image from i.imgur.com]

In this interview they talk a little bit about the Firmware Card at: http://www.inclusive.co.uk/lib/downloads/adaptive-firmware-card.pdf

Quote
PAUL: We... [mingled voices]. Yeah, basically it... it was becoming clear to us, and I think at the time it was becoming clear to everybody, uh, and Gregg Vanderheiden, uh, I remember would talk about this very eloquently, that we needed a way to do transparent access to computers, so that we weren’t just running programs that we’d written for special needs but... but that you could run the... that Kris or Steve could run a computer just like anybody else, and they could do anything with a computer. And at that... at that point in time, um, I remember Gregg was espousing an idea of nested computers -- that you would have two computers, and that one computer would run the special-input routine, um, that was, you know, one or two switches, and it would then send its results to the other computer as if you were using the keyboard.

Um, at the same time, I had been doing a lot of adapting programs, and... and I could... I saw that there were advantages to being able to stay within the... the one computer and to be able to have the routine running alongside the program you were adapting, so that it could use the same display and make use of the same resources -- um, sound and the... and if you had an Echo speech synthesizer it could do that.

And so I began thinking about this problem, and I was trying to find a way to combine these two things: to have transparency but also be able to, um,... to make it seem like you’re just adapting the program that you’re running. And ultimately what I came up with was the Adaptive Firmware Card.

Uh, in effect what the Adaptive Firmware Card did was it sort of turned the Apple II, which was a... a single-tasking machine -- you could only run one program at a time -- it sort of turned it into a multi-tasking machine. It was sort of a poor man’s version of a multi-tasking machine, because you might say it was a double-tasking machine -- you... you could run the program plus the input routine as the second routine -- but it was a circuit board that went in the computer, and the adaptive routine that you wanted to run resided on the... on the card, and the hardware played tricks so that when you wanted to use that routine it would interrupt the... the program that was running, and then it would bring up a scanning array or do Morse code or do whatever was necessary, uh, to allow you to generate text with one or two switches. And that was, um,... and I guess that was... that was something new. And ... and I remember, I don’t know how, but somehow Gregg Vanderheiden found out about this. I can’t remember... I might’ve written a letter to the Trace Center, uh, or there was a contest about that time at Johns Hopkins..



There's a great article in the 1982 Byte with all kinds of technical details and schematics:

https://archive.org/details/byte-magazine-1982-09-rescan/page/n277


https://archive.org/details/byte-magazine-1982-09-rescan/page/n299 is where it talks about how it takes over the Apple II. It's a pretty fascinating read where it emulates keyboard inputs and paddle inputs.

[Linked Image from i.imgur.com]

There's also a page where someone gets one running and talks about the history of one switch gaming:

http://www.pixsoriginadventures.co.uk/apple-ii-adaptive-firmware-card/

The a2dp has a few docs and pictures:

https://mirrors.apple2.org.za/Apple...0Cards/Other/Adaptive%20Firmware%20Card/

The later ones had an onboard 65816 and 32KB of ram, but the very first ones were mainly EPROM and RAM.

Re: c64 super sketch [Re: Golden Child] #116293 10/27/19 02:14 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
One thing leads to another and I looked briefly at the Muppet Learning Keys by Koala and I think that this same approach of loading a picture and clicking the mouse could work well with it.

Putting a grid on top of the overlay in gimp makes a perfect alignment.

[Linked Image from i.imgur.com]

A little bit of watchpointing the paddles at c064 and c065 and disassembling and we can find the table of the Apple II Muppet discovery disk.

The overlay maps to the table at EF00.

[Linked Image from i.imgur.com]

Re: c64 super sketch [Re: Golden Child] #116294 10/27/19 03:40 PM
Joined: Mar 2001
Posts: 16,394
R
R. Belmont Online Content
Very Senior Member
Online Content
Very Senior Member
R
Joined: Mar 2001
Posts: 16,394
There's a post on Brutal Deluxe's site that explains the Muppet Learning Keys.

https://www.brutaldeluxe.fr/projects/muppet/index.html

Re: c64 super sketch [Re: R. Belmont] #116295 10/27/19 04:50 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
Thanks, RB! That was just what I needed!


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

Re: c64 super sketch [Re: Golden Child] #116296 10/27/19 05:38 PM
Joined: Feb 2014
Posts: 358
G
Golden Child Online Content OP
Senior Member
OP Online Content
Senior Member
G
Joined: Feb 2014
Posts: 358
There's a driver disk for the Muppet Keys for at least the atari that will allow you to use it as a regular keyboard which was a neat concept.

(pictures from atariage)

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

and a post I found that was interesting:

[Linked Image from i.imgur.com]

Page 1 of 6 1 2 3 4 5 6

Who's Online Now
4 registered members (Olivier Galibert, MAMEBase, Breiztiger, 1 invisible), 149 guests, and 3 spiders.
Key: Admin, Global Mod, Mod
ShoutChat Box
Comment Guidelines: Do post respectful and insightful comments. Don't flame, hate, spam.
Forum Statistics
Forums9
Topics8,722
Posts114,651
Members4,873
Most Online510
Aug 26th, 2019
Powered by UBB.threads™ PHP Forum Software 7.7.3