Log inRegister an accountBrowse CSDbHelp & documentationFacts & StatisticsThe forumsAvailable RSS-feeds on CSDbSupport CSDb Commodore 64 Scene Database
You are not logged in - nap
CSDb User Forums


Forums > C64 Coding > Making your own cartridge ROM
2009-02-28 20:15
Frantic

Registered: Mar 2003
Posts: 1627
Making your own cartridge ROM

Hello!

I wonder if there is any good reference/tutorial/info text material on creating your own cart ROM (primarily in "Retro Replay format"). I never did this myself, but I am planning to do so. I know there is a special "header" ("CBM80" or something?) first of all which makes the c64 recognize that a cart is plugged in, and then there is all the bank switching stuff (there are docs from Jens Schoenfeld on that I guess), and also assemblers with special features for memory bank handling and so on (dreamass has some features in this direction, or...?). Is the "action replay" source code available somewhere (I heard that this was "floating around on the net")? I think all kind of info like this would be nice to have on http://codebase64.org

The main point here is not primarily that I wouldn't be able to figure things out from various sources of information, but rather that it would be nice to collect already existing info on this on codebase, since there isn't that much on this topic there right now.

Anyone got some info/tutorials on this topic? If there isn't any available, then I would love to see someone write a little about the requirements for making cart software on codebase. Yeah?

(By the way.. Is it just me, or do you people also get "Frantic" as one of the hotlinks on google when searching for "CSDb"? Huh? I guess I must be a very important c64 scener? ;)

//FTC
2009-02-28 21:15
AlexC

Registered: Jan 2008
Posts: 293
Frantic, first of all there are 2 different types of cartridges - those for C64 and 128 only. The CBM80 signature at $8004 is for C64 only cartridges. C128 uses different scheme.

In c64:
You have to remember that cart memory is mapped from $8000-$9FFF and $A000-$FFFF. If you use high memory where normally kernel resides that you can use your own IRQ, NMI and RESET vectors.

Starting from $8000 you usually put:

$8000 - $8002 cold start vector
$8003 - $8003 warm start vector
$8004 - CBM80 signature ($C3, $C2, $CD, $38, $30)

However there are other schemes possible - Trilogic Expert is a good example. It uses NMI line. Don't forget about Ultimax mode - some old cars used it.

If you like I can do a short write up about it.
2009-02-28 23:24
Frantic

Registered: Mar 2003
Posts: 1627
So... You can't call Kernal routines from a cart?

I'd be most happy if you wrote something up on this topic!
2009-03-01 00:06
chatGPZ

Registered: Dec 2001
Posts: 11113
most (all?) freezer carts use the ultimax mode extensivly =)
2009-03-01 02:05
Twoflower

Registered: Jan 2002
Posts: 434
A very good and thorough explanation of the different cartridge format aswell as how carts uses the GAME, EXROM, ROML and ROML lines to arrange where in memory the cart is switched in can be found in the document CRT.TXT by Peter Schepers.

This is a document i've learned most stuff about carts from. The CRT.TXT is included in the FORMATS.ZIP-file which is a part of 64Copy V4.42. Information of some carttypes are missing from there though - most notably the Silverrock, Prophet 64 and the Mssiah carts.
2009-03-01 08:36
tlr

Registered: Sep 2003
Posts: 1714
Quote: So... You can't call Kernal routines from a cart?

I'd be most happy if you wrote something up on this topic!


You can usually use kernal. The kernal is unavailable only in Ultimax mode.

The "normal" cartridge operation modes are described in PRG.
PRG: C64 Memory Maps (several pages)

On top of this there are a lot of cartridges that incorporates extra registers that bankswitches and/or switches between the cartridge modes dynamically.
These registers are commonly mapped to the I/O1 and I/O2 regions ($DExx and $DFxx)

Kernal startup sequence:
>C:fffc  E2 FC
.C:fce2   A2 FF      LDX #$FF
.C:fce4   78         SEI
.C:fce5   9A         TXS
.C:fce6   D8         CLD
.C:fce7   20 02 FD   JSR $FD02    ; check for CBM80
.C:fcea   D0 03      BNE $FCEF
.C:fcec   6C 00 80   JMP ($8000)
.C:fcef   8E 16 D0   STX $D016
.C:fcf2   20 A3 FD   JSR $FDA3    ; setup I/O
.C:fcf5   20 50 FD   JSR $FD50    ; setup zp + memsize
.C:fcf8   20 15 FD   JSR $FD15    ; setup vectors
.C:fcfb   20 5B FF   JSR $FF5B    ; setup screen
.C:fcfe   58         CLI
.C:fcff   6C 00 A0   JMP ($A000)


EDIT: and the terminology LORAM/HIRAM/CHAREN are bits 0, 1 and 2 of $01 respectively.
EXROM and GAME are signals from the cartridge to the C64.
ROML, ROMH, I/O1 and I/O2 are chip select signals from the C64 to the cartridge.
2009-03-01 09:45
Angel of Death

Registered: Apr 2008
Posts: 210
Have been fiddling around with creating my own 'virtual' cartridges using the CRT format in emulators.
Probably the easiest thing, at least that's what I did, is to, indeed start with, peter schepers description of the CRT format and then with that same program copy the different chip packets from various cartridges and see how they work.
Because you have to keep in mind that the CRT format emulates physical hardware that belongs to the appropriate cartridge. (mainly concerning reading one or more mem locations regulating bank selection)
I wrote a source code for tass1.45 that constructs the headers and stuff and in which I can cut and paste the actual c64 code.
Haven't really figured out, yet, how all the control lines and the dynamic bankswitching works, though...

Source code is too big to put here. Could mail it, if you wish.

Oh, it isn't on codebase yet because it is in a bit of an embryonic state as far as annotation and structure goes.
2009-03-01 13:17
WVL

Registered: Mar 2002
Posts: 886
What kind of rom do you want to make anyway? There's already functionality in the flashprogram to flash standard programs in a bank and make them runnable. (maybe you didnt know this?)
2009-03-01 14:29
enthusi

Registered: May 2004
Posts: 675
I did some CRT "research" as well for the upcoming NEH edition :)
If you want a generic 8 or 16 KB cart its rather simple and a header I coded is pretty short.
Fiddling with EXROM and GAME is mostly only necessary when you use BASIC routines.
You can simply blend the ROM in/out via $01 otherwise.
So no need to have THAT specific hw knowledge about the crt.
The simple kind works well in vice and MMCR 0.55 too.
I can clean my code and post it too if someone needs it.
You have to be a bit careful about the INIT routines since some use BASIC area and you usually wont need them anyway.

cheers,
enthusi
2009-03-01 16:56
AlexC

Registered: Jan 2008
Posts: 293
Quote: So... You can't call Kernal routines from a cart?

I'd be most happy if you wrote something up on this topic!


No, you actually can - it all comes down to memory management. However keep in mind that most advance carts like Action Replay had their own RAM (this is why there are 2 method for writing into that RAM).

Code inside the EPROM is just part of the bigger design, especially if you want more than swapping out 8 or 16k.

I'll write something for codebase64 than. It's in line with my update regarding detecting cartridges :)
2009-03-01 22:24
Frantic

Registered: Mar 2003
Posts: 1627
Thank you everyone for your replies!

@WVL: The program in question is rather large (would require switching between ROM banks), and the reason for putting it into a cart would be to have as much ordinary C64 ram free as possible in order to make yet another bunch of features possible (so, not just loading it quickly from cart, even though the quick "loading" is also part of the picture here of course).

By the way.. I still wonder about assemblers.... Is there a reason for why you would need any other feature for assembling a cart ROM than some "pseudo PC" directive, like the one you use for drive code for example?

//FTC
2009-03-02 07:55
JackAsser

Registered: Jun 2002
Posts: 1989
Quote: Thank you everyone for your replies!

@WVL: The program in question is rather large (would require switching between ROM banks), and the reason for putting it into a cart would be to have as much ordinary C64 ram free as possible in order to make yet another bunch of features possible (so, not just loading it quickly from cart, even though the quick "loading" is also part of the picture here of course).

By the way.. I still wonder about assemblers.... Is there a reason for why you would need any other feature for assembling a cart ROM than some "pseudo PC" directive, like the one you use for drive code for example?

//FTC


Not sure but when I've had ideas like this I've always thought it would be nice if $8xxx and $axxx went into separate binaries. This can easily be achieved with ca65/ld65 by choosing a file as output on the MEMORY directives in the link file instead of the ordinary "%O".
2009-03-02 08:41
AlexC

Registered: Jan 2008
Posts: 293
Quote: Thank you everyone for your replies!

@WVL: The program in question is rather large (would require switching between ROM banks), and the reason for putting it into a cart would be to have as much ordinary C64 ram free as possible in order to make yet another bunch of features possible (so, not just loading it quickly from cart, even though the quick "loading" is also part of the picture here of course).

By the way.. I still wonder about assemblers.... Is there a reason for why you would need any other feature for assembling a cart ROM than some "pseudo PC" directive, like the one you use for drive code for example?

//FTC


Despite standard *=$xxxx and .offs(et) directives you don't need a lot more. Macros are really hand but this applies to any code. Directives like include and incbin or similar are also useful becouse you can easly attach binary data or have separate files for $8000 and $A000 for example. Local labels and blocks are also usefull, especially if you have a lot of loops.

Basic "copy protection" scheme is also quite easy to develop using almost any assembler as it goes likes this:

*=$8009
         lda #$02
         sta crash
crash:   nop
2009-03-02 08:48
enthusi

Registered: May 2004
Posts: 675
AlexC, hehe.
Well why make it that complicated?
I just exomized the game, wrote a small 5 liner to copy $8000-xxxx to $0801.
It uses PSEUDOPC $0400.
The cart-reset-routine copies the "launcher" to $0400, executes it and somewhere near $0430 it says JMP $080b.
Case solved.
Of course you need the CRT header.
Ans fiddling with $01 allows you to copy beneath $8000 as well.
And yes, that is NOT useful as copyprotection at all since the raw PRG is there all the time...


;this is for a 8KB cart!!
*=$0000
.asc "C64 CARTRIDGE "
.byte $00,$00 ;header length
.byte $00,$40 ;header length
.word $0001 ;version
.word $0000 ;crt type
.byte $00 ;exrom line
.byte $01 ;game line
.byte $00,$00,$00,$00,$00,$00 ;unused
.asc "CRT TITLE"
name
.dsb ($0040-name),0
;chip packets
.asc "CHIP"
.byte $00,$00,$20,$10 ;chip length
.byte $00,$00 ;chip type
.byte $00,$00 ;bank
.byte $80,$00 ;adress
.byte $20,$00 ;length
;ROM part
;---------------------------------
*=$8000
.word launcher
.word launcher
.byte $c3 ;c
.byte $c2 ;b
.byte $cd ;m
.byte $38 ;8
.byte $30 ;0

launcher
sei
stx $d016
jsr $fda3 ;prepare irq
jsr $fd50 ;init memory
jsr $fd15 ;init i/o
jsr $ff5b ;init video
cli
;inc $d020
;jsr $e453 ;load basic vectors
;jsr $e3bf ;init basic ram
jsr start_all ;move basic prg
jmp $0400

;jsr $a68e
;jmp $a7ae

; inc $d020 only for basic
;ldx #$fb
; txs
;---------------------------------
start_all
lda $d011
and #%11101111
sta $d011

ldx #$00
sa1
lda movecode1,x
sta $0400,x
inx
bne sa1
rts
;------------------------------
movecode1
;803d here
*=$0400
movecode2
basic_move
ldx #$00
bm1
lda main_file_start,x
bm2
sta $0801,x
inx
bne bm1
inc bm1+2
inc bm2+2
lda bm1+2
cmp #$c0
bne basic_move
jmp $080b
movecode3
;---------------------------------
*=movecode1+(movecode3-movecode2)
main_file_start
.bin 2,0,"game.bin"
main_file_end

.dsb ($a000-main_file_end),0
2009-03-02 11:15
Frantic

Registered: Mar 2003
Posts: 1627
Sorry if I was unclear. My question was not intended to be about assemblers in general, but about assemblers with features that may be especially useful when assembling a cart ROM file.
2009-03-02 12:01
AlexC

Registered: Jan 2008
Posts: 293
Quote: Sorry if I was unclear. My question was not intended to be about assemblers in general, but about assemblers with features that may be especially useful when assembling a cart ROM file.

Old Turbo Assemblers starts at $9000 so it leaves small address space for you. Turbo Macro Assembler uses memory from $8000 so it's not really suitable unless you are using version for RR (or RR the one embedded in Cyberpunx rom). You can also use Turbo Action ROM. Anyway the best option today is probably to use any cross assembler like dremass or kick.

enthusi: I like your idea - neat trick. But you don't need CRT header if you are going to burn the EPROM. Anyway using RR/Retro Replay mapper is the best option I suppose. There is interesting project regarding cartridge for c128 going on too with similar cart mapper capabilities.
2009-03-02 13:54
Frantic

Registered: Mar 2003
Posts: 1627
Sorry for being unclear again... :)

I was of course referring to cross assemblers in this case, since testing a big cart ROM image on the real hardware during development would be... too much. :)

Btw, I added some bits and pieces of info on codebase now, from various sources. The "crt.txt", enthusis code posted here and another similar short snippet of code that I found lying around on my harddrive.

http://codebase64.org/doku.php?id=base:thirdparty

//FTC
2009-03-02 22:09
AlexC

Registered: Jan 2008
Posts: 293
Frantic to conclude: I doubt there are any special functions in assemblers for cartridge development because even native ones like TA supports all requirements. It's the burner software that can be more or less helpful in the process.
2009-03-03 08:55
Frantic

Registered: Mar 2003
Posts: 1627
Yes.. After a brief look into various assemblers (like dreamass, WLA DX, ca65) who mention cartridge programming in their docs, it seems to be mostly about providing "segments", i.e. supporting cart coding on a conceptual level. Functionally, a lot of assemblers are of course able to pull the stunt of having several pieces of code in the binary with the same start address...
2009-03-03 09:22
chatGPZ

Registered: Dec 2001
Posts: 11113
personally i think dreamass is the only assembler that has actually useful support for building cartridges.... segments alone do not help much.
2009-03-03 09:33
Frantic

Registered: Mar 2003
Posts: 1627
Okay.. So.. What about dreamass makes it useful for cart programming, on top of the support for segments?
2009-03-03 09:38
chatGPZ

Registered: Dec 2001
Posts: 11113
two very useful things that i didnt find anywhere else are:
- a pseudo op that returns the bank number of a symbol. this allows to very easily build tables with bank/adress for a cross-bank-call-api
- the assembler can put functions into banks as they fit automatically, so you dont have to worry about memory layout.
2009-03-03 10:04
Frantic

Registered: Mar 2003
Posts: 1627
Ah! That sounds very useful indeed! Thanks for the info!
2009-03-03 20:50
AlexC

Registered: Jan 2008
Posts: 293
Speaking about assemblers another "useful" feature popped into my head, but just for limited number of users and coders: Z80 support for C128. Again the use will be quite limited as Z80 speed is not astonishing to say at least but maybe if you were to build cart for CP/M... any other ideas? ;)
2009-03-06 23:17
Bregalad
Account closed

Registered: Jul 2008
Posts: 42
Speaking of that I have some experience with WLA-DS beacuse I wanted to code for many platforms.
It is pretty good, but it assumes the code is compiled into ROM, and does lack some proper supports for relocatable code (altough there is workarrounds for it).

Handling bankswitching with is is very convenient overall. A big drawback is that the author is not really caring any longer about it like he was before.
2009-07-27 20:31
Frantic

Registered: Mar 2003
Posts: 1627
Quote: two very useful things that i didnt find anywhere else are:
- a pseudo op that returns the bank number of a symbol. this allows to very easily build tables with bank/adress for a cross-bank-call-api
- the assembler can put functions into banks as they fit automatically, so you dont have to worry about memory layout.


@Groepaz: I looked in to this today, but didn't really find any info about this stuff that you mention here in the DreamAss docs. Are these features undocumented, or so?
2009-07-28 22:06
AlexC

Registered: Jan 2008
Posts: 293
Quote: @Groepaz: I looked in to this today, but didn't really find any info about this stuff that you mention here in the DreamAss docs. Are these features undocumented, or so?

I think it's segment functionality but I'm not sure. Take a look at chapter 5 of DreamAss documentation if I remember correctly.
2009-07-29 13:10
Frantic

Registered: Mar 2003
Posts: 1627
I eventually found the info. It was "hidden" in a section called "Terms" (I would have called that section "operators" or something like that). There is a operator called "segmentof" which is what I was looking for (and this operator is not mentioned in the manual section which deals with segments). I still didn't find any info regarding Groepaz second statement though...
2009-09-03 20:11
AlexC

Registered: Jan 2008
Posts: 293
@enthusi: nice code :) Thanks for posting. The only problem is when your code after relocation goes higher than $8000 I guess.

I need to take a look at crt description because right now I'm looking for a solution to load packed code from cartridge and than relocate it into RAM and than have RAM at $0000-$FFFF or at least up to $CFFF.
2009-09-19 22:40
MisterMSK
Account closed

Registered: Jul 2009
Posts: 37
@enthusi: I was curious. What compiler you used for your cartridge making code?
RefreshSubscribe to this thread:

You need to be logged in to post in the forum.

Search the forum:
Search   for   in  
All times are CET.
Search CSDb
Advanced
Users Online
Menace/Spaceballs
Apollyon/ALD
Krill/Plush
macx
CA$H/TRiAD
Guests online: 135
Top Demos
1 Next Level  (9.8)
2 Mojo  (9.7)
3 Coma Light 13  (9.7)
4 Edge of Disgrace  (9.6)
5 Comaland 100%  (9.6)
6 No Bounds  (9.6)
7 Uncensored  (9.6)
8 Wonderland XIV  (9.6)
9 Bromance  (9.6)
10 Memento Mori  (9.6)
Top onefile Demos
1 It's More Fun to Com..  (9.7)
2 Party Elk 2  (9.7)
3 Cubic Dream  (9.6)
4 Copper Booze  (9.5)
5 TRSAC, Gabber & Pebe..  (9.5)
6 Rainbow Connection  (9.5)
7 Onscreen 5k  (9.5)
8 Wafer Demo  (9.5)
9 Dawnfall V1.1  (9.5)
10 Quadrants  (9.5)
Top Groups
1 Oxyron  (9.3)
2 Nostalgia  (9.3)
3 Booze Design  (9.3)
4 Censor Design  (9.3)
5 Crest  (9.3)
Top Swappers
1 Derbyshire Ram  (10)
2 Jerry  (9.8)
3 Violator  (9.8)
4 Acidchild  (9.7)
5 Starlight  (9.6)

Home - Disclaimer
Copyright © No Name 2001-2024
Page generated in: 0.075 sec.