Jump to content
ZackAttack

Designing a cartridge that supports 100% C/C++ game development

Recommended Posts

I was thinking about a raspberry pi, they start at about 700mA. They contain a powerful processor, lots of storage, network. Everything you could ever want. Easy to obtain and relatively inexpensive.

Share this post


Link to post
Share on other sites

I was thinking about a raspberry pi, they start at about 700mA. They contain a powerful processor, lots of storage, network. Everything you could ever want. Easy to obtain and relatively inexpensive.

700mA is definitely excessive considering the power adapter is rated for 500mA. The ARM inside the Harmony cart not enough to work with? :ponder:

Share this post


Link to post
Share on other sites

Yes, that is indeed excessive. I'm guessing that my cartridge will draw about 100ma.

 

It's not like a raspberry pi would fit inside a cart anyway. Why not just use an external power supply for it?

 

It's been my experience that you can supply 5V to the Atari through the cartridge port and it will run just fine without the Atari being plugged in. Which is useful for allowing an external device to hard reset the system.

Share this post


Link to post
Share on other sites

The MCU I plan to use for this cart has built in USB hardware. It can be configured as either a device or host. I'm leaning towards wiring it up as a host and exposing a standard usb female connector on the cartridge. Then you could plug in a gamepad, wifi, rockband guitar etc as long as you add support for it in the software. The other option would be to make it a usb device so it could be programmable from a PC similar to how the harmony operates. I always just copy games to the harmony via the SD card and have never tried using it as a USB device, so it seems like providing a host port could be far more useful. I also plan on putting a placeholder for a JTAG connector on the PCB for those who want to modify the firmware. Any thoughts on use cases that I may have overlooked?

 

I finally have all the parts I ordered and am working on putting together the next prototype. Should have more to share in the next few weeks. Assuming my toaster oven soldering skills are good enough.

  • Like 2

Share this post


Link to post
Share on other sites

Yes, that is indeed excessive. I'm guessing that my cartridge will draw about 100ma.

 

It's not like a raspberry pi would fit inside a cart anyway. Why not just use an external power supply for it?

 

It's been my experience that you can supply 5V to the Atari through the cartridge port and it will run just fine without the Atari being plugged in. Which is useful for allowing an external device to hard reset the system.

That's a dangerous proposition. What if you plug the cart usb to power the Atari and plug in the stock adapter? Then you're mixing power planes, which can lead to unsafe current loops and potentially fry something. If you do this, you'll need to isolate the power planes for the cart and system. Even then you aren't truly safe, because bad things tend to happen when you supply signal to 5V logic chips without a power supply.

Share this post


Link to post
Share on other sites

Got most of the soldering done tonight. Pretty sure this will be the last breadboard prototype I do with such a large pin count. After the first side I was seriously regretting not just going straight to a circuit board prototype. Now I just need to strip the other end of all 140 wires.

 

post-40226-0-92991800-1452484369_thumb.jpg

post-40226-0-39492600-1452484377_thumb.jpg

  • Like 1

Share this post


Link to post
Share on other sites

And then there was that one bug, where it seemed like it was transmitting data but things just didn't work properly.

You'll spend the next week trying to hunt down the issue only to discover there was a bad solder point on IO pin 37

 

140 wires...I certainly hope it just works ;)

Share this post


Link to post
Share on other sites

And then there was that one bug, where it seemed like it was transmitting data but things just didn't work properly.

You'll spend the next week trying to hunt down the issue only to discover there was a bad solder point on IO pin 37

 

140 wires...I certainly hope it just works ;)

yeah, I hope so too. Since the input and output from VCS are on separate ports I'm going to try to make a self test program to help find bad solder joints.

Share this post


Link to post
Share on other sites

Got most of the soldering done tonight. Pretty sure this will be the last breadboard prototype I do with such a large pin count. After the first side I was seriously regretting not just going straight to a circuit board prototype. Now I just need to strip the other end of all 140 wires.

 

attachicon.gifMCU LQFP144 (1).jpg

attachicon.gifMCU LQFP144 (2).jpg

You must have a lot of patience! :o

Share this post


Link to post
Share on other sites

It took a couple of weeks to get the ARM tools working, but I was able to successfully program and debug via JTAG finally. I've deleted the FPGA from the design, turns out it's cheaper and simpler to just use a dual core MCU. One core will take the place of the FPGA to keep everything in sync with the 6507 and the other core will be free to run the game code. This should also make it easier to support existing Atari games and the various banking schemes. DPC+ games might be possible to support too, need to figure out if the instructions set used by the harmony is a subset of the set used in the SAM4C32.

 

Still trying to decide how much more to prototype on the breadboards before I order a custom PCB.

  • Like 2

Share this post


Link to post
Share on other sites

After a lot of testing and analisys I've concluded that a dual core MCU will not be cabaple of meeting my timing requirements. The Atmel SAM4C32E I was testing with is just not able to read and write to the I/O pins fast enough for what I want to do. The good news is that I am now a lot more skilled with Atmel Studio, ASF, and logic analyzers :)

 

What's really interesting is the variation of bus signals between my 2600 Jr. and Light Sixer. One maintains A12 in a high state when accessing two consecutive ROM locations and the other has a short period where A12 goes low before going high again.

 

Finally, I have confirmed that you can force the entire data bus low in order to hold the 6507 in a predictable state. It will continually jump to $0000 and execute a BRK instruction (SP will overflow). So if the cart forces the data bus low when in power on reset it can take a long time to startup without worrying about the 6507 executing a halt instruction. Once everything is initialized simply put the reset vector at $fffe/$ffff.

Share this post


Link to post
Share on other sites

Now that all the experimental research is complete, it is time to start work on the schematic and PCB. The plan is to design a large amount of flexibility into the PCB so that it can be used to create several different configurations ranging in cost and capabilities. If multiple projects share the same PCB a large quantity can be ordered in order to reduce cost.

 

There is a 10 board minimum and I'm only planning on using 5 boards. One for each configuration plus a spare. I'm willing to give away the other 5 boards to anyone who is interested in being an alpha tester. I'll mail you the board and you will have to assemble it with your own components. If anyone is interested please PM me with which configuration you plan to use and what you want to use it for.

 

Here are the planned configurations:

post-40226-0-99232300-1477281402_thumb.png

 

Updated Block Diagram:

post-40226-0-76100500-1477286399_thumb.png

Configuration Matrix.pdf

Edited by ZackAttack
  • Like 1

Share this post


Link to post
Share on other sites

Yes, that is indeed excessive. I'm guessing that my cartridge will draw about 100ma.

 

It's not like a raspberry pi would fit inside a cart anyway. Why not just use an external power supply for it?

 

It's been my experience that you can supply 5V to the Atari through the cartridge port and it will run just fine without the Atari being plugged in. Which is useful for allowing an external device to hard reset the system.

While most vintage 5V game systems can be safely operated in this manner, care must be made to ensure the console is not powered on simultaneously with external power supply. Otherwise the internal 7805 regulator will "fight" with the external 5V supply to provide power to the system.

 

In such cases, if the cart needs external power because it draws excessive current (>100mA), it may be a better option to leave the VCC pin on the cartridge disconnected and to only use a common ground connection. Then the cart can be safely receive power from an external 5V source, ie USB port, and additionally the USB port can be used to program the device as well as provide supplementary power. The I/O logic between the system and cart will provide 5V logic to the bus without creating potentially damaging current loop issues caused by dueling 5V supplies.

 

EDIT: Oops, quoted an older post. Good luck with your project and keep us posted on updates. Looking good! :cool:

Edited by Kosmic Stardust
  • Like 1

Share this post


Link to post
Share on other sites

EasyEda.com has been selected for the schematic and PCB tool. The tool is free and easy to use and it makes it easy to share the project with others. They also have a PCB service with competitive pricing. Hopefully this will make it easy for anyone to order their own boards if they want.

 

I'm been making good progress on the schematic. Since the FPGA I/O pins can be routed inside the chip itself I'm not connecting them in the schematic. Instead they will be connected during the PCB phase so they can be connected in a manner that reduces vias as much as possible.

 

Here's what I've completed so far. Very preliminary, but most of the pieces are there. The goal is to have a fully assembled board by the end of the year and enough software to run 4k games in early January.

 

post-40226-0-89535700-1477884060_thumb.png

 

post-40226-0-67676400-1477884364_thumb.png

 

Edit: Uploaded better PCB image.

Edited by ZackAttack

Share this post


Link to post
Share on other sites

That is a ton of power for only 4k games. Will it eventually support larger sizes? Couldn't the FPGA alone clone just about any kind of 8-bit / 16-bit computer? It's like a Ferrari engine in a shopping cart. :)

  • Like 1

Share this post


Link to post
Share on other sites

Running a 4k game is just the first software milestone. It's a the first of many steps in bringing up the new hardware. If everything goes as planned with the DRAM it should support up to 4MB games. The FPGA only has 4000 4-bit LUTs. It's more like a civic engine in a shopping cart.

 

Also, keep in mind that even a 4k game can take advantage of the FPGA. It could easily have a full PF buffer with hardware support for 4way scrolling.

  • Like 2

Share this post


Link to post
Share on other sites

Running a 4k game is just the first software milestone. It's a the first of many steps in bringing up the new hardware. If everything goes as planned with the DRAM it should support up to 4MB games. The FPGA only has 4000 4-bit LUTs. It's more like a civic engine in a shopping cart.

 

Also, keep in mind that even a 4k game can take advantage of the FPGA. It could easily have a full PF buffer with hardware support for 4way scrolling.

 

How does bus stuffing work? I'm a novice at this but here is my very simplified understanding:

 

Atari requests data at an address. The address is made up of 12 (11?) signals. These are single bits? On or off?

 

The EEPROM gets the address, locates the data at the address, and outputs a byte back to the CPU (8 lines, single bits?)

 

So, to stuff the bus, you load the data on the 8 bit line without having to do a "LDA" instruction? Which saves the CPU from having to do it?

 

How do you intercept the LDA command before the CPU sees it?

 

Finally, how do you program the game in C when the Atari expects a 6507 binary? Are you converting the C code to assembly/binary (like batari basic) and loading it on the EEPROM?

Share this post


Link to post
Share on other sites

How does bus stuffing work? I'm a novice at this but here is my very simplified understanding:

 

Atari requests data at an address. The address is made up of 12 (11?) signals. These are single bits? On or off?

 

The EEPROM gets the address, locates the data at the address, and outputs a byte back to the CPU (8 lines, single bits?)

 

So, to stuff the bus, you load the data on the 8 bit line without having to do a "LDA" instruction? Which saves the CPU from having to do it?

 

How do you intercept the LDA command before the CPU sees it?

 

Finally, how do you program the game in C when the Atari expects a 6507 binary? Are you converting the C code to assembly/binary (like batari basic) and loading it on the EEPROM?

 

The address is made up of 13 bits (signals) and data is made up of 8. Generally we refer to the group of signals as a bus. In the case of the VCS there is the 13bit address bus and 8bit data bus that are brought out to the cart connector. There is also a control bus with a few additional signals, but the control bus is not accessible from the game cartridge port. From the perspective of the 6507 the address bus is an output only and the data bus is bidirectional. Each cycle the data bus will be assigned a direction depending on which cycle of which instruction. Well behaved hardware will only drive the signal on the data bus when it has been told to do so by the processor. In the case of a typical 4K ROM this is whenever the address is in the range $1000-$ffff aka A12 is a logic 1. Keep in mind the convention is to start at A0 so A12 is actually the 13th/highest bit.

 

Bus stuffing works by driving a signal on the bus at the same time as the processor which overrides the data the processor is outputting with a new value. This allows TIA registers to be updated faster because you no longer have to load the value and store the value. Instead the 6507 is instructed to store repeatedly and each time it tries to write the value it's writing is overridden by the bus stuffing circuitry. Here is an example of what it would look like to update the GRP0 and COLUP0 registers without and with bus stuffing. There is also a second way to do bus stuffing that involves overriding both the address and data bus at the same time. This can allow even faster register updates than the first way but is more timing sensitive and difficult to implement. As you can see the number of cycles it takes to update two TIA registers is 10, 6, and 5 for normal, data stuffing, and both stuffing respectively. Looking at it differently a 76 cycle scanline has enough time for 15, 25, or 30 TIA register updates depending on which mode you use.

Cycle:       0      1      2      3      4      5      6      7      8      9      

Normal:
Instruction: |---LDA #xx--||-------STA zp------||---LDA #xx--||-------STA zp------|
Address:     Out    Out    Out    Out    Out    Out    Out    Out    Out    Out
             $f000  $f001  $f002  $f003  $001b  $f004  $f005  $f006  $f007  $0006  
Read/Write:  Read   Read   Read   Read   Write  Read   Read   Read   Read   Write  
Data:        In     In     In     In     Out    In     In     In     In     Out
             $a9    $11    $85    $1b    $11    $a9    $22    $85    $06    $22    

Bus stuffing data bus:
Instruction: |-------STA zp------||-------STA zp------|
Address:     Out    Out    Out    Out    Out    Out    
             $f000  $f001  $001b  $f002  $f003  $0006  
Read/Write:  Read   Read   Write  Read   Read   Write  
Data:        In     In     Stuff  In     In     Stuff
             $85    $1b    $11    $85    $06    $22    

Bus stuffing address and data bus:
Instruction: |--------------ROL zp-------------|
Address:     Out    Out    Out    Stuff  Stuff   
             $f000  $f001  $00ff  $001b  $0006    
Read/Write:  Read   Read   Read   Write  Write  
Data:        In     In     In     Stuff  Stuff
             $26    $ff    $ff    $11    $22        

Programming the VCS can be viewed as simply updating TIA registers at specific times. If we have an abstraction that allows you to specify a list of registers to update and the hardware can consume that list you can take the 6507 out of the equation. Any microcontroller inside the game cart can be programmed in C/C++ to generate the list of registers to update in a memory buffer. What's really nice about doing it this way is that the hardware takes care of timing the actual TIA updates. None of the code needs to be timed anymore. If you take more than 1/60th of a second to update the buffer it can simply redraw the same buffer twice. No more screen rolling because you ran out of time.

 

  • Like 5

Share this post


Link to post
Share on other sites

How does bus stuffing work? I'm a novice at this but here is my very simplified understanding:

 

This is the slide I'll be using for my presentation this evening:

post-3056-0-06684300-1478968839_thumb.png

 

You can use STA, STX, or STY. For our implementation we chose STY.

 

The driver for the Harmony/Melody cart emulates the entire cartridge, even the ROM, so it monitors the ROM values returned to the 6507. Bus Stuffing can be turned on/off, so we only turn it on for the display kernel as we don't need bus stuffing during overscan or vertical blank. When it's on it triggers the bus stuffing logic when a ROM value of $84 is returned, that's the hex value for the STY zero page instruction:

 

STY (STore Y register)

Affects Flags: none

MODE           SYNTAX       HEX LEN TIM
Zero Page     STY $44       $84  2   3
Zero Page,X   STY $44,X     $94  2   4
Absolute      STY $4400     $8C  3   4


 

Since it's all triggered by the STY, there's no LDY to intercept.

 

There's 6507 code and ARM code inside the ROM as there's 2 CPUs being used - the 6507 inside the Atari and the ARM inside the Harmony/Melody. The 6507 only executes the compiled 6507 assembly code, the ARM only executes the compiled C code.

  • Like 1

Share this post


Link to post
Share on other sites

 

The address is made up of 13 bits (signals) and data is made up of 8.

 

Wouldn't 13 signals allow the Atari to see 8k instead of 4? Is one of the lines on the address bus used for something else (the direction?)

 

 

 

Programming the VCS can be viewed as simply updating TIA registers at specific times.

 

That's a nice abstraction I hadn't considered.

 

 

 

This is the slide I'll be using for my presentation this evening:

attachicon.gifScreen Shot 2016-11-12 at 10.40.04 AM.png

 

 

In the slide you have at the bottom that you only drive 0s and that 1s are dangerous. Why is this? Is it because if you drive a 1 on a data line that is already a 1 you're doubling the voltage?

 

Thanks for the excellent explanation!

Share this post


Link to post
Share on other sites

Wouldn't 13 signals allow the Atari to see 8k instead of 4? Is one of the lines on the address bus used for something else (the direction?)

 

The 6507 can access 8K, the 2600 is arranged so one address line determines 4K cartridge port or 4K internal hardware. Most of the addresses are mirrored, which means things appear at multiple locations. For example RAM appears at $0080-$00FF, $0180-$01FF, etc.

 

In the slide you have at the bottom that you only drive 0s and that 1s are dangerous. Why is this? Is it because if you drive a 1 on a data line that is already a 1 you're doubling the voltage?

I don't know, I'm not that familiar with how the hardware works at that level. Chris, who's writing the BUS Driver for the Harmony/Melody hardware, mentioned it after reviewing the presentation.

Share this post


Link to post
Share on other sites

1+1 doesn't double the voltage; you just get 1. Ditto for 0+0=0, but bizarre things can happen when two active signals are present. 0+1 and 1+0 are examples of bus conflicts where the chips basically fight each other. One sinks current and one sources current so whichever chip wins can be unpredictable. This can lead to unintended consequences in games creating glitches or even crash the hardware, but generally the currents involved are low enough that the chips do not sustain actual damage. You cannot damage the hardware by loading bad software in other words.

  • Like 1

Share this post


Link to post
Share on other sites

Okay, so let me see if I have this right:

 

The 6507 is instructed to STY $FF in an infinite loop.

 

At the same time, C code is running on an ARM core that is updating registers in memory based on how you've programmed your game.

 

The ARM is timed to copy the registers (bus stuff) to the data bus when it intercepts the STY command. It does this continually so the game never rolls or bounces.

 

The 6507 stores the Y register depending on what data was on the bus. Updating TIA and playfield and sprite information.

 

In this arrangement, the 6507 is really just a bus driver and the ARM does all the logic and memory manipulation. That's how you can program your game in C!

 

The Harmony cartridge implementation differs in that it stores a compiled binary in flash. It watches the address lines and then fetches data from a flash location and outputs that on the data bus. Sort of like a normal cartridge but with the benefits of not having to program an EPROM.

 

In this implementation, how do you get input information from the Atari RIOT? You can write data to the Atari, but how do you read joysticks and paddles?

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...