Sunday, September 24, 2017

Writing to both the Third Millenium Arcade Board and the Super Sprite.


I wanted to write to the Third Millenium Arcade Board and the Super Sprite, but there's just one problem: The Super Sprite has its addresses at $C0F0 and $C0F1.

You can write to those addresses just fine in machine language with STA $C0F1 but an AppleSoft POKE doesn't work the same.

Applesoft POKE actually executes a STA ($50),Y to address $C0F1, but that actually reads $C0F1 before it writes $C0F1. It's kind of counter intuitive that you would have a read when you're trying to write something, but that's the wacky design of the 6502.

That read has the side effect of resetting the TMS9918A address pointer so when it writes, the TMS9918 thinks you want to specify the low byte of the address pointer. Each time you write $C0F1 it resets that pointer so you never actually finish setting the high byte of address pointer.

So you have to resort to assembly language, and I poke a little routine into memory and then call it. STA absolute doesn't have the same problem as the STA ($50),Y register indirect mode and it will write to $C0F1 properly without reading it first.

This applesoft program is horribly unoptimized, I just wanted something that would work.

It you let it run for a few minutes it will display the following:

(hint: display the frameskip with F11, set the frameskip to 6 with F8/F9 and unthrottle with F10 to speed things up)

./mame64 apple2e -sl4 arcbd -sl7 ssprite










The simple routines I poke into memory and call:

4000: 2 writes to C0F1 to set an address, reading C0F1 first to make sure we reset the address register
     It's a register write if the second byte has the hi byte set.
4014: same routine as 4000
     It's an address write if the second byte has bit 6 set, bit 6 clear if just to read.
4028: write to C0F0, write DATA register
403C: read from C0F0, read DATA register

]CALL -151

*4000L

4000-   AD F1 C0    LDA   $C0F1
4003-   A9 0F       LDA   #$0F
4005-   8D F1 C0    STA   $C0F1
4008-   A9 87       LDA   #$87
400A-   8D F1 C0    STA   $C0F1
400D-   60          RTS   
400E-   00          BRK   
400F-   00          BRK   
4010-   00          BRK   
4011-   00          BRK   
4012-   00          BRK   
4013-   00          BRK   
4014-   AD F1 C0    LDA   $C0F1
4017-   A9 00       LDA   #$00
4019-   8D F1 C0    STA   $C0F1
401C-   A9 78       LDA   #$78
401E-   8D F1 C0    STA   $C0F1
4021-   60          RTS   
4022-   00          BRK   
4023-   00          BRK   
*L

4024-   00          BRK   
4025-   00          BRK   
4026-   00          BRK   
4027-   00          BRK   
4028-   A9 78       LDA   #$78
402A-   8D F0 C0    STA   $C0F0
402D-   60          RTS   
402E-   00          BRK   
402F-   00          BRK   
4030-   00          BRK   
4031-   00          BRK   
4032-   00          BRK   
4033-   00          BRK   
4034-   00          BRK   
4035-   00          BRK   
4036-   00          BRK   
4037-   00          BRK   
4038-   00          BRK   
4039-   00          BRK   
403A-   00          BRK   
*L

403B-   00          BRK   
403C-   AD C0 C0    LDA   $C0C0
403F-   8D 4E 40    STA   $404E
4042-   60          RTS   
4043-   00          BRK   
4044-   00          BRK   
4045-   00          BRK   
4046-   00          BRK   
4047-   00          BRK   
4048-   00          BRK   
4049-   00          BRK   
404A-   00          BRK   
404B-   00          BRK   
404C-   00          BRK   
404D-   00          BRK   
404E-   00          BRK   
404F-   00          BRK   
4050-   00          BRK   
4051-   00          BRK   
4052-   00          BRK   

Monday, September 18, 2017

Copy the Apple ii text screen to the Third Millenium Arcade Board

So I thought I'd see if I could copy the apple ii's text screen to the tms9918.

Once I've loaded the font into the tms9918 memory, I can just copy bytes from the apple ii's text screen to the tms9918's memory.

Yes, it's not optimized, because I was assembling it by hand with the CALL -151 monitor.

So to write bytes to the TMS9918, you write the low byte of the address to $C0C3, then the high byte with bit 6 set (so we add 64 or $40). We want to write to location zero, so that means writing a $00, then a $40 to $C0C3.

Now any bytes written to $C0C2 will go to that address and then auto-increment the destination address.

We use the routine at $FBC1 to calculate the address of the text line given in A. That clobbers A so we have to restore it. It stores the address in $28 and $29. We use LDA ($28),Y to access the text memory, then STA it to $C0C2. Keep going until we get 32 chars in the line CPY #$20, and then keep going until we've done 24 lines CPX #$18.

4030-   A9 00       LDA   #$00
4032-   8D C3 C0    STA   $C0C3
4035-   A9 40       LDA   #$40
4037-   8D C3 C0    STA   $C0C3
403A-   A9 00       LDA   #$00
403C-   AA          TAX   
403D-   8A          TXA   
403E-   20 C1 FB    JSR   $FBC1
4041-   A0 00       LDY   #$00
4043-   48          PHA   
4044-   B1 28       LDA   ($28),Y
4046-   8D C2 C0    STA   $C0C2
4049-   68          PLA   
404A-   C8          INY   
404B-   C0 20       CPY   #$20
404D-   30 F4       BMI   $4043
404F-   E8          INX   
4050-   E0 18       CPX   #$18
4052-   30 E9       BMI   $403D
4054-   60          RTS   

If you're wondering why it's multicolored, I was experimenting with the TMS9918 color table.



My uploaded font, with the characters from 0-127 copied to 128-255 and colored with the color table. The color table for the 32x24 mode 0 has 32 bytes total: a single color for 8 character patterns.





I think the crazy colors look cool. Distracting but kind of cool.

Sunday, September 17, 2017

Fun with TMS9918 fonts on the Third Millenium Arcade Board





So you have to upload fonts to the TMS9918 to get it to display anything textwise.

I came across this great thread about ti fonts by sometimes99er where he has put together a bunch of great fonts in gif format:

http://atariage.com/forums/topic/165697-fonts/

There was one font in particular that is near and dear to me: The classic Amiga font.

Let's see if we can get the Apple II Third Millenium Arcade Board's TMS9918 to display it.

First, I thought I'd use HTML5 and firefox to generate the DATA statements for Applesoft:

So we create a canvas, draw the 0236.chr.gif into the canvas, and use getImageData() to get access to the data and generate a bunch of DATA statements.






This HTML5 generates the following DATA statements.





and we paste this into mame's apple2 driver with SHIFT+Scroll Lock to enter it into our basic program:

and I choose background B = 4 and foreground F = 15 for white text on blue for that classic look.




Friday, September 15, 2017

Disassembling the VDPTEST program for the Third Millenium Enginnering Arcade Board

So I thought I'd have a look at what the VDPTEST program actually does.

Doing a PR#1 and LOAD VDPTEST and LIST gets me:



What you see the basic program do is to BLOAD VDPTST which goes to address $1000 (4096) and it will patch it with the proper io addresses for the slot number. So every occurrence of C0C0 and C0C1 will get patched.

It will CALL 4096 after the patching and it writes the entire 16K ($4000) of the TMS9918 with the value held in memory location $104C and then reads it back, comparing it to what's in $104C.

If it gets an error, it writes $00 to address $2000 (8192), but if everything is cool it writes $CC to address $2000 (8192).

What is complete BS is the error reporting in the basic program. It looks for error information at 8193, 8194, 8195 and 8196, but quite frankly I don't see where it's getting this information, because the assembly program just doesn't write those locations. There should be an STX $2003, an STY $2004 or something.

It'll tell you there's an error, but the information reported is bogus.

I kept trying to figure out what the CALL 768 does. The CALL 768 in the program is setup in the HELLO program on the disk. It just resets the apple video output on reset according to the REM remarks.






So for fun, I thought I'd patch it by hand with the monitor so it would send the proper values to the basic program if there were an error. There's nothing like changing those values by hand.

I tested it using the mame debugger and changing the values in the TMS9918 vram by hand to simulate a memory error.

What was really driving me crazy is that the basic VDPTEST program kept patching the addresses after I'd changed them. A little "175 GOTO 210" fixed that. I changed the instances of $C0C1 to $C0C3 and $C0C0 to $C0C2 to get it to run under mame 189.



Monday, September 11, 2017

Samsung 171v and gddccontrol

There's no monitor file for the Samsung 171v (SAM0063.xml)l in ddccontrol-db, but there is a listing for the Samsung 173s in the (SAM00A3.xml) file which is extremely similar.

So we'll copy that and put it into /usr/share/ddccontrol-db/monitor/SAM0063.xml.


There's no speakers so we'll take the 62 entry out of the caps add line.






So if you're curious, here's the full ddccontrol -c -p -d output:




Tuesday, September 5, 2017

Fun with the Synetix SuperSprite board

I was looking at the old Creative Computing article again about the Third Millenium Arcade Board and the Synetix Supersprite board and I thought, why not see if I could make a copy of the a2arcadebd.cpp and see if the SuperSprite would work?


So let's take a2arcadebd.h and a2arcadebd.cpp and search and replace arcadebd with ssprite, and change a few of the strings, and save it as a2ssprite.h and a2ssprite.cpp. The Synetix Supersprite demos hang when it tries to do speech, so we hook up a tms5220, copying lines from a2echoii.cpp.

src/devices/bus/a2bus/a2ssprite.h






src/devices/bus/a2bus/a2ssprite.cpp






and we need to hook it up in the apple2e driver with an #include and a SLOT_INTERFACE and put a couple of lines in bus.lua for a2ssprite.h and a2ssprite.cpp:





After you do this and compile with make you can launch mame with the -sl7 ssprite parameter and run the supersprite demo programs.

./mame64 apple2e -sl7 ssprite -flop1 "StarSprite Demonstration.DSK"










from "Third Millenium Arcade Board - Article Creative Computing 1984.pdf"


Saturday, August 26, 2017

Getting the Third Millenium Arcade Board MLDEMOS to run

I loaded up the MLDEMOS on the Third Millenium arcade board and took a look at where it was hanging up.

./mame64 apple2e -sl4 arcbd -flop1 Amparcade_1983_Third_Millenium_Engineering_Corporation.do -debug


It was spinning in a loop around 088e and proceeding no further.

I set a break point at 088e with "bpset 088e" and after it hit the breakpoint, did a "history".

It was obviously writing data to $c0c1 and $c0c0.



I also did a disassembly from 800 to 1800 with "dasm mldemo.asm,800,1000" to take a look at.


less mldemo.asm | grep '$c0c1'
08E4: AD C1 C0 lda $c0c1
0990: 8D C1 C0 sta $c0c1
0993: 8E C1 C0 stx $c0c1
0A80: 8D C1 C0 sta $c0c1
0A83: 8C C1 C0 sty $c0c1



less mldemo.asm | grep '$c0c0'
0859: 8D C0 C0 sta $c0c0
09B3: 8D C0 C0 sta $c0c0
09DE: 8D C0 C0 sta $c0c0
0A09: 8D C0 C0 sta $c0c0
0A3B: 8D C0 C0 sta $c0c0
0A68: 8D C0 C0 sta $c0c0


The arcade board is supposed to be in slot#4 which maps to the $c0cx memory space, and the code in a2arcade.cpp looks like this:

======================================================


/*
    C0nx map:
    0 - TMS read vram
    1 - TMS read status
    2 - TMS write vram
    3 - TMS write register
    5 - AY register select
    6 - AY data
*/


void a2bus_arcboard_device::write_c0nx(address_space &space, uint8_t offset, uint8_t data)
{
 switch (offset)
 {
  case 2:
   m_tms->vram_write(space, 0, data);
   break;

  case 3:
   m_tms->register_write(space, 0, data);
   break;

  case 5:
   m_ay->address_w(space, 0, data);
   break;

  case 6:
   m_ay->data_w(space, 0, data);
   break;
 }
}






So if it's writing c0c0 and c0c1, nothing is happening since we've got no cases for that.

So let's add case 0 and case 1: (assuming they're just like case 2 and 3)
=================================



void a2bus_arcboard_device::write_c0nx(address_space &space, uint8_t offset, uint8_t data)
{
 switch (offset)
 {
  case 0:
   m_tms->vram_write(space, 0, data);
   break;
  case 1:
   m_tms->register_write(space, 0, data);
   break;
  case 2:
   m_tms->vram_write(space, 0, data);
   break;

  case 3:
   m_tms->register_write(space, 0, data);
   break;

  case 5:
   m_ay->address_w(space, 0, data);
   break;

  case 6:
   m_ay->data_w(space, 0, data);
   break;
 }
}



And things start working!








Happy guy from the MLDEMO hotel scene: