How to build own cartridge for Commodore 64.
Firstly we need know what C64 sharing on the expansion port:
Now we need know what for above signals/lines they are and haw they works so
Important information: 6510/8500 CPU have own internal port under $00 (direction) and $01 (port) where 3 lowest bits they are responsible for memory configuration:
o Bit 0 – LORAM o Bit 1 – HIRAM o Bit 2 – CHAREN
After RESET or POWER ON above 3 bits have logic 1 (HIGH STATE) value, so when have all high state in the C64 PLA working and can cooperated with cartridge and setting memory for CPU access like bellow:
• If cartridge is enabled $8000 to $9FFF can be shadowed by ROM/RAM of cartridge (IF EXROM = 0)
• If cartridge is enabled BASIC ROM $A000 to $BFFF can be shadowed by ROM/RAM of cartridge (IF GAME = 0)
R/W registers. This area is not full address decode and is mirrored to $D3FF after every one 63 ($3F) bytes, so for example $D040 is this same like $D000. VIC can be IRQ interrupts source.
registers WRITE ONLY area except any register for paddles. Like before here is no full address decode and SID region is repeated to $D7FF
1000 bytes, where active are lowest 4 bits (16 colors possibility) in every one byte.
can be invoke IRQ – interrupts. This 16 R/W registers are mirrored 15 times over the $DCFF
can be invoke NMI – interrupts. This 16 R/W registers are mirrored 15 times over the $DCFF
This area is for external hardware, here we can use this for cartridge control. This AREA IS CONNECTED with /IO1 line WHEN LORAM,HIRAM and CHAREN have high state, and when CPU addressing this area this line going to logical 0 (LOW state). Also this area can be shadowed by external cartridge RAM/ROM
This area is for external hardware, here we can use this for cartridge control. This AREA IS CONNECTED with /IO1 line WHEN LORAM,HIRAM and CHAREN have high state, and when CPU addressing this area this line going to logical 0 (LOW state). Also this area can be shadowed by external cartridge RAM/ROM.
Some times this area can be shadowed by external ROM/RAM of cartridge, when will be choose ULTIMAX MODE (GAME = 0, EXROM = 1). So by this trick we can changed the RESET, IRQ and NMI VECTORS, where they are placed
RESET - $FFFC/$FFFD LO/HI byte. IRQ - $FFFE/$FFFF LO/HI byte. NMI - $FFFA/$FFFB LO/HI byte.
So when LORAM is enabled (1) C64 PLA can be sending information to cartridge via ROML line (setting logical 0) when CPU addressing area $8000 - $9FFF ONLY WHEN EXROM = 0 and cartridge in this place can set up own ROM/RAM . Read phase only access.
WHEN HIRAM is enabled (1) PLA can be sending information to cartridge via ROMH line (setting logical 0) when CPU addressing area $A000 - $BFFF ONLY WHEN GAME = 0 and cartridge in this place can set up own ROM/RAM . Read phase only access.
In SPECIAL CASE – ULTIMAX MODE - WHEN HIRAM is enabled (1) PLA can be sending information to cartridge via ROMH line (setting logical 0) when CPU addressing area $E000 - $FFFF ONLY WHEN GAME = 0 AND EXROM = 1 and cartridge in this place can set up own ROM/RAM – Is not so easy guys, ULTIMAX MODE is a bit complex, and I don’t describe all of this subject. Read phase only access.
OK – now we know, what for they are LORAM, HIRAM, how they have state after RESET and when we can using them and where they are placed.
Now we can considering, how we can using any other signals included in expansion port for our own purposes. So naturally and how I mentioned before we should knowing how working 4 signals connected functionally between self
– from C64 SIDE IT’S INPUT LINE and this is information from the C64 PLA for manipulating ROMH (set to 0) when CPU addressing $A000 - $BFFF area or $E000-$FFFF in ULTIMAX MODE. Definitely is the OUTPUT LINE from cartridge side and this line manipulating cartridge always.
– OUTPUT LINE from C64 side, and for cartridge is a INPUT line – Is a lead out of address decoder signal and this line going to low state (logical 0) when CPU addressing $A000 - $BFFF area or $E000-$FFFF in ULTIMAX MODE. When CPU addressing any other area this line going up to HIGH (1) immediately. So cartridge can using information from this line and getting shadowing mentioned above areas by own ROM or RAM. BUT STOP STOP STOP - Be patient be cause is not all information for cartridge, when hi can do this !!! For read operations only.
Now we can properly suspect this same function for EXROM and ROML for $8000-$9FFF area and indeed.
– from C64 SIDE IT’S INPUT LINE and this is information from the C64 PLA for manipulating ROML (set to 0) when CPU addressing $800-$9FFF. OUTPUT LINE from cartridge side and this line manipulating cartridge always.
– OUTPUT LINE from C64 side, and for cartridge is a INPUT line – Is a lead out of address decoder signal and this line going to low state (logical 0) when CPU addressing $8000-$9FFF. When CPU addressing any other area this line going up to HIGH (1) immediately. For read operations only.
ALLWAYS REMEMBER IT WORK WHEN LORAM FOR EXROM AND HIRAM FOR GAME IS ENABLED (1)
Now we must considering 4 possibilities settings GAME and EXROM and what’s going on here:
GAME = 1, EXROM = 1 Nothing to do. No any information send from C64 to cartridge via ROML or ROMH They are still in HIGH (1)
GAME = 1, EXROM = 0 8KB cartridge in $8000-$9FFF area possibility. ROML still work. ROMH always in HIGH state (1)
GAME = 0, EXROM = 0 16 KB cartridge in $8000-$BFFF area possibility. ROML and ROMH both still work.
GAME = 0, EXROM = 1 – ULTIMAX MODE 8KB cartridge in $A000-$BFFF and $E000-$FFFF area possibility. ROMH still work. ROML always in HIGH state (1). Most often this same data are visible in $A000-$BFFF and $E000-$FFFF. Mirror, but we can try exchanged kernel. However be carefully. ULTIMAX MODE is a bit complicated. You need to read “C64 programmers reference guide”
OKAY like before we have 2 next signals called:
When CPU addressing $DE00-$DEFF area this line going to LOW state (0). After this immediately go back to (1). OUTPUT LINE from C64 side and of course INPUT LINE from cartridge side. So cartridge can know when CPU addressing this page. THIS LINE WORKING FOR READ AND WRITE OPERATIONS
have this same function like /IO1 for $DF00-$DFFF area. It’s simple lead out of address decoder. R/W access like /IO1
– by this line using as OUTPUT from cartridge side, cartridge can be invoke IRQ interrupts by set this line to (0). Normal state for this line I (1). But remember interrupt here is invoke by LOW STATE.
– by this line using as OUTPUT from cartridge side, cartridge can be invoke NMI interrupts by FALLING EDGE of this line. Most often used for take over control in freezers in ULTIMAX MODE. After FALLING EDGE on this line CPU going via NMI VECTOR located under ($FFFA) so of course when we talking about the falling edge so normal state of this line is (1). When in this time is kernel replaced the CPU starting program including in the cartridge ROM/RAM.
– input line for cartridge – when CPU is busy hi set this line as logic (0). This is a information for cartridge “don’t do anything I’m busy”. This line working all the time, for example when VIC refreshing data for charset in every one 8th line CPU is stopped for 40 cycles. Also when VIC fetching sprite data BA going to LOW state.
– rectangular signal about 8MHZ freq, signal is lead out from VIC after gone every one pixel on the screen line.
– very important line which send information when CPU read or write datas. Most often from cartridge side is input line. When CPU doing write operation this line going to LOW STATE (0), for read (1). By this line we can recognize what CPU doing and which one phase we awaiting. If cartridge want send data to data bus we need high state on this line, if cart need read data from C64 we need low state R/W.
– by this line we can obtain DIRECT MEMORY ACCESS. When some lines they are not input only from cartridge side. However be carefully, DMA is not so easy to use. More experience you need for this.
– very important last one line. This line synchronize all R/W operations. Here we have rectangular signal freq about 1MHZ. When PHI2 have LOW state we have phase when VIC refreshing RAM. CPU working like this: When going RISING EDGE of PHI2 the CPU setting data, hi have 500ns time for this. After 500ms going FALLING EDGE of PHI2 and IN THIS MOMENT data are strobe. General rules for properly work is:
OKAY we have short describe of expansion port Commodore 64, now we can get considerations what going on with this lines, how used they.
EXAMPLE: We want enable 8KB cartridge in $8000 - $9FFF area how to do it ?
For this we need information:
For this we need set the EXROM line to LOW state, also we need connected cartridge ROM to address bus and data bus, and checking when /ROML have a LOW state.
This is a very simple and scheme bellow show properly connections:
Now we can considering how we can get any data from CPU from /IO1 area. For this we need a few information:
Ad1 – For 1st point we need set the check /IO1 signal. Ad2 – Second information provide for us the R/W line, when it is in LOW state we can check 3rd value Ad3 – Basically we check PHI2 line
In other words:
IF /IO1 = 0 and R/W = 0 and PHI2 EDGE GOING TO DOWN THEN WE CAN CATCH DATA FROM DATABUS
This task doing our cartridge. For more clarity we need check the timing diagrams this lines:
You can see when data are stabilized and how many times are present after falling edge of PHI2.
Sadly if we don’t use for this any CPLD or FPGA we need to find any logic unit which will be able doing this function. And for example 74LS138 can do it.
The Q0 (Y0) otput line most often is in high state. When A,B,C, G2A, G2B input lines are in low state (ZAP, RW, IO1) and PHI2 = 1 then Q0 take a LOW state and when PHI2 is going down the Q0 line send write strobe for catch data by 74LS273. After this when PHI2 will be changed to high, also RW and IO1 going to high state Q0 line is HIGH.
White line - moment of latching data from data bus
|ID||Name||Designator||Footprint||Quantity||Manufacturer Part||Manufacturer||Supplier||Supplier Part||Price||LCSC Assembly||Mounted||nameAlias|