http://sleepingelephant.com/ipw-web/bul ... 3&start=11
Well, he asked
I answered the question in a way.Jeff-20 wrote:What would I need to make a cart out of my single file basic code? I would like a flash option so I could replace it with other games...
Anyway...
I'll continue my comments about this project here.
This is the current cartridge prototype, I have marked the new part with a nice red-ish digital pen. I'll probably etch a stand alone PCB sometime - that would decrease the wiring a lot...
Note that this cart has all the pads for the expansion port - most carts do not - that way you can't get the I/O3 signal in an easy way.
Current problem:
I don't think I have balanced the power-up reset circuit very well. I have three 1Mohm parallell resistors in series with a 1 µF cap, and a 1Mohm resistor parallell with the cap. The circuit is between +5V and GND, signal is taken between the parallell cap+resistor and the parallell resistors.
So I have about 333kohm in series with the parallell cap and resistor.
When I start up from cold - the VIC has been off for some time I never manage to get a start directly and have to flip the ON/OFF switch to get it going. Most of the time it starts up when I restart after trying a game... As I have mentioned before I have to hold M when starting to get into the menu else "Mole Attack" will start - as it is in a Mole Attack shell I thought that was a nice stealthy way... I'll probably put a sticker on the back "HOLD M WHEN STARTING FOR MULTICART MODE".
I added an OR-gate to A12 of the flashrom, that way I can use all the 8kB space when adding a 4kB game. I simply set the sixth latch by adding 32 to the block position - upper half of block 27 is adressed 27+32.
I know it's a little bit odd, but I didn't want to change what was already done.
When the latch is 0 the OR-gate from normal A12 of the expansion port is enabled as usual.
Very neat.
I added two 4kB Imagic-games in one slot.
I have added my favorites and then random games, I might sort the list when it's full.
These are the current games of my 2 Mbit multicartridge (256kB):
- Block 0-2: menu and these:
SLAP DAB
SNAKE
SPEEDSKI
DRIVER!
ROCKET COMMAND
TANK VS UFO
BUILDING
BLITZ
--------------------------- end of nostalgic old BASIC favorites
memory block ... title
03 MOLE ATTACK
04 THE SKY IS FALLING
05 TITAN
06 TANK ATAK
07 SUPER SMASH
08 STAR TREK S.O.S
09 SPIDERS OF MARS
10 SATELLITES AND METEORITES
11 PRINCESS AND FROG
12 OMEGA RACE
13 MONSTER MAZE
14 JELLY MONSTERS
15 CHOPLIFTER
16 TUTANKHAM
17 PARATROOPER
18 CONGO BONGO
19 COSMIC JAILBREAK
20 GALAXIAN
21 JUPITER LANDER
22 PAC-MAN
23 RADAR RAT RACE
24 ARCADIA
25 BANK ROBBER
26 DRAGONFIRE
27 DEMON ATTACK + ATLANTIS
28
29
30
31
I might repeat some data so that you don't need to look back in the other thread.
I use a 39SF020 flashrom, which is a 5V programmable circuit, it has 32 pins and I therefore added a socket to the original 24 pin holes.
All the pins that didn't match the original circuit was bent up and tape was put above the solder pads to avoid connection. Some pins were then simply rewired and the rest of them connected to two other IC circuits.
Latch 74LS174, it's like a memory of six bits, it reloads the output on a clock pulse - on positive flank. Clock was connected to I/O3 - and nothing else was needed there as I get a nice zero-level 1 µs (I think it was - look at oscilloscope pictures in old thread) pulse when writing to the memory area $9C00-9BFF which is associated with this I/O. The positive flank is exactly in the middle of the data-pulse that is loaded into the latch inputs.
To zero the latch on startup a circuit was added to set the RESET signal before cartridge loads up. What is needed is two resistors, a capacitor and a Schmitt-trigger type inverter circuit - I had a 74HC14 at home, so I used that. You should usually not mix HC and HCT or LS circuits, but as I only used the output from the HC-ciruit to the 74LS174 I was OK. The in-signal comes from +5V via the components described.
Here's a hand drawn schematic:
I have written some code to make a menu and copy the basic games that are on the cart back to RAM where they belong:
The code is adapted to DASM.
Code: Select all
; Fredric Blåholtz
; Favorite games in a cartridge
; 2008
; Thanks to Anders Carlsson
; for all the help!
;
; dasm game.asm -f3 -ogame.bin to compile
processor 6502
dest = $1001 ; destination adress
org $A000
; ==============================================================
; Startup code for autostart
; ==============================================================
.word inits ; Entry point for power up
.word restore ; Entry point for warm start (RESTORE)
.byte "A0" ; 'A0CBM' autoboot string
.byte $C3,$C2,$CD
inits:
;Kernel Init
jsr $FD8D ; RAMTAS - Initialise System Constants
jsr $FD52 ; Restore Kernal Vectors (at 0314)
jsr $FDF9 ; Init I/O
jsr $E518 ; Init I/O
;BASIC Init (Partial)
lda #8 ; Set screen colors
sta $900F ; black+black
jsr $E45B ; Init Vectors
jsr $E3A4 ; Init BASIC RAM
jsr $E404 ; write start text
; copy "set latch and reset"-program to buffer
lda #$A9
sta $02A1
lda #$01
sta $02A2
lda #$8D
sta $02A3
lda #$01
sta $02A4
lda #$9C
sta $02A5
lda #$4C
sta $02A6
lda #$22
sta $02A7
lda #$FD
sta $02A8
;$02A1 lda #$01
; sta $9C01
; jmp $FD22
jsr $ffe4
cmp #$4d ; check if M is pressed
beq menu ; if it is - continue to menu else
lda #$03 ; run Mole attack on Block 3
jmp start_game
; ==============================================================
; Menu Screen
; ==============================================================
menu:
ldx #$00
printmenu:
lda menuscreen,x
beq printmenu.end2 ; branch when data is 0
jsr $ffd2
inx
jmp printmenu
printmenu.end2:
ldx #$00
printmenu.end:
lda menuscreen.end,x
beq checkkeys ; branch when data is 0
jsr $ffd2
inx
jmp printmenu.end
checkkeys:
jsr $ffe4
key1:
cmp #$31 ;1
bne key2
jmp copy_slap1
key2:
cmp #$32 ;2
bne key3
lda #$01
jmp game1
key3:
cmp #$33 ;3
bne key4
lda #$02
jmp game1
key4:
cmp #$34 ;4
bne key5
lda #$01
jmp game2
key5:
cmp #$35 ;5
bne key6
lda #$01
jmp game3
key6:
cmp #$36 ;6
bne key7
lda #$01
jmp game4
key7:
cmp #$37 ;7
bne key8
lda #$01
jmp game5
key8:
cmp #$38 ;8
bne key9
lda #17
jmp start_game
key9:
cmp #$39 ;9
bne key0
lda #15
jmp start_game
key0:
cmp #$30 ;0
bne keyQ
lda #5
jmp start_game
keyQ:
cmp #81 ;Q
bne keyW
lda #6
jmp start_game
keyW:
cmp #87 ;W
bne keyE
lda #7
jmp start_game
keyE:
cmp #69 ;E
bne keyR
lda #8
jmp start_game
keyR:
cmp #82 ;R
bne keyT
lda #9
jmp start_game
keyT:
cmp #84 ;T
bne keyY
lda #10
jmp start_game
keyY:
cmp #89 ;Y
bne keyU
lda #11
jmp start_game
keyU:
cmp #85 ;U
bne key_space
lda #12
jmp start_game
key_space:
cmp #32
beq menu2
jmp checkkeys
; write second menu
menu2:
ldx #$00
printmenu2:
lda menuscreen2,x
beq menu3 ; branch when data is 0
jsr $ffd2
inx
jmp printmenu2
; menudata > 255, split in 2 parts
menu3:
ldx #$00
printmenu3:
lda menuscreen3,x
beq checkkeys2 ; branch when data is 0
jsr $ffd2
inx
jmp printmenu3
checkkeys2:
jsr $ffe4
key21:
cmp #$31 ;1
bne key22
lda #13
jmp start_game
key22:
cmp #$32 ;2
bne key23
lda #14
jmp start_game
key23:
cmp #$33 ;3
bne key24
lda #4
jmp start_game
key24:
cmp #$34 ;4
bne key25
lda #16
jmp start_game
key25:
cmp #$35 ;5
bne key26
lda #3
jmp start_game
key26:
cmp #$36 ;6
bne key27
lda #18
jmp start_game
key27:
cmp #$37 ;7
bne key28
lda #19
jmp start_game
key28:
cmp #$38 ;8
bne key29
lda #20
jmp start_game
key29:
cmp #$39 ;9
bne key20
lda #21
jmp start_game
key20:
cmp #$30 ;0
bne key2Q
lda #22
jmp start_game
key2Q:
cmp #81 ;Q
bne key2W
lda #23
jmp start_game
key2W:
cmp #87 ;W
bne key2E
lda #24
jmp start_game
key2E:
cmp #69 ;E
bne key2R
lda #25
jmp start_game
key2R:
cmp #82 ;R
bne key2T
; clear screen to avoid seeing garbage
lda #$93
jsr $ffd2
lda #25 ; Set screen colors
sta $900F ; to all white
lda #26
jmp start_game
key2T:
cmp #84 ;T
bne key2Y
lda #2
jmp game2
key2Y:
cmp #89 ;Y
bne key2U
; clear screen to avoid seeing garbage
lda #$93
jsr $ffd2
lda #25 ; Set screen colors
sta $900F ; to all white
lda #27
jmp start_game
key2U:
cmp #85 ;U
bne space2
lda #$93 ; clear, white screen
jsr $ffd2
lda #25
sta $900F
lda #[27+32]
jmp start_game
space2:
cmp #32
bne go_checkkeys
jmp menu
go_checkkeys:
jmp checkkeys2
start_game:
sta $02A2
jmp $02A1
copy_slap1:
ldx #$05 ; number of 256 byte pages to copy
lda #<start_s1 ; lower byte of address
sta $FB ; store in $00FB
lda #>start_s1 ; upper byte of address
sta $FC ; store in $00FC
jsr copy_data
; Start program
jsr $C659 ; clr
jmp $C7AE ; run
copy_slap2:
ldx #$0B ; number of 256 byte pages to copy ( 11 pages )
lda #<start_s2 ; lower byte of address
sta $FB ; store in $00FB
lda #>start_s2 ; upper byte of address
sta $FC ; store in $00FC
jsr copy_data
; Start program
jsr $C659 ; clr
jmp $C7AE ; run
; ==============================================================
; Copy data, parameters already set
; ==============================================================
copy_data:
lda #<dest ; lower byte of address
sta $FD ; store in $00FD
lda #>dest ; upper byte of address
sta $FE ; store in $FE
loop2:
ldy #$00 ; Y = 0
loop1:
lda ($FB),Y ; A = contents of $00FB plus offset Y
sta ($FD),Y ; $00DF + offset Y = A
iny ; increase Y
bne loop1 ; Branch on Result not Zero to L1
inc $FC ; increase value at $00FC (upper byte of start address)
inc $FE ; increase value at $00FE (upper byte of dest. address)
dex ; X = X - 1 (decrease pages left to copy)
bne loop2 ; Branch on Result not Zero to L2
rts
; ==============================================================
; Handle the RESTORE key
; ==============================================================
restore:
jmp $FEC7 ; Continue as if no cartridge installed
; ==============================================================
; Program data
; ==============================================================
start_s1:
incbin "games/S1-crunched.bin"
end_s1:
start_s2:
incbin "games/Slap-Dab2.bin"
end_s2:
; ==============================================================
; Define some common PETSCII codes
; http://sta.c64.org/cbm64petkey.html
; ==============================================================
CLRHOME = $93
RVSON = $12
RVSOFF = $92
CR = $0D
WHITE = $05
GREEN = $1E
BLUE = $1F
YELLOW = $9E
CYAN = $9F
; ==============================================================
; Menu screen
; ==============================================================
menuscreen:
.byte WHITE, CLRHOME
.byte " CHOOSE GAME", CR, CR
.byte RVSON, WHITE, "1", RVSOFF, YELLOW, " SLAP DAB", CR
.byte RVSON, WHITE, "2", RVSOFF, GREEN, " SNAKE", CR
.byte RVSON, WHITE, "3", RVSOFF, WHITE, " SPEEDSKI", CR
.byte RVSON, WHITE, "4", RVSOFF, YELLOW, " DRIVER!", CR
.byte RVSON, WHITE, "5", RVSOFF, CYAN, " ROCKET COMMAND", CR
.byte RVSON, WHITE, "6", RVSOFF, WHITE, " TANK VS UFO", CR
.byte RVSON, WHITE, "7", RVSOFF, GREEN, " BUILDING", CR
.byte RVSON, WHITE, "8", RVSOFF, WHITE, " PARATROOPER", CR
.byte RVSON, WHITE, "9", RVSOFF, YELLOW, " CHOPLIFTER", CR
.byte $00
menuscreen.end:
.byte RVSON, WHITE, "0", RVSOFF, CYAN, " TITAN", CR
.byte RVSON, WHITE, "Q", RVSOFF, GREEN, " TANK ATAK", CR
.byte RVSON, WHITE, "W", RVSOFF, WHITE, " SUPER SMASH", CR
.byte RVSON, WHITE, "E", RVSOFF, YELLOW, " STAR TREK S.O.S", CR
.byte RVSON, WHITE, "R", RVSOFF, CYAN, " SPIDERS OF MARS", CR
.byte RVSON, WHITE, "T", RVSOFF, GREEN, " SATS AND METEORITES", CR
.byte RVSON, WHITE, "Y", RVSOFF, WHITE, " PRINCESS AND FROG", CR
.byte RVSON, WHITE, "U", RVSOFF, YELLOW, " OMEGA RACE", CR,CR
.byte " ", RVSON, WHITE, "SPACE", RVSOFF, YELLOW, " NEXT PAGE", CR
.byte BLUE
.byte $00
menuscreen2:
.byte CLRHOME, WHITE
.byte " CHOOSE GAME", CR, CR
.byte RVSON, WHITE, "1", RVSOFF, GREEN, " MONSTER MAZE", CR
.byte RVSON, WHITE, "2", RVSOFF, WHITE, " JELLY MONSTERS", CR
.byte RVSON, WHITE, "3", RVSOFF, YELLOW, " THE SKY IS FALLING", CR
.byte RVSON, WHITE, "4", RVSOFF, CYAN, " TUTANKHAM", CR
.byte RVSON, WHITE, "5", RVSOFF, GREEN, " MOLE ATTACK", CR
.byte RVSON, WHITE, "6", RVSOFF, WHITE, " CONGO BONGO", CR
.byte RVSON, WHITE, "7", RVSOFF, YELLOW, " COSMIC JAILBREAK", CR
.byte RVSON, WHITE, "8", RVSOFF, CYAN, " GALAXIAN", CR
.byte $00
menuscreen3:
.byte RVSON, WHITE, "9", RVSOFF, GREEN, " JUPITER LANDER", CR
.byte RVSON, WHITE, "0", RVSOFF, WHITE, " PAC-MAN", CR
.byte RVSON, WHITE, "Q", RVSOFF, YELLOW, " RADAR RAT RACE", CR
.byte RVSON, WHITE, "W", RVSOFF, CYAN, " ARCADIA", CR
.byte RVSON, WHITE, "E", RVSOFF, GREEN, " BANK ROBBER", CR
.byte RVSON, WHITE, "R", RVSOFF, WHITE, " DRAGONFIRE", CR
.byte RVSON, WHITE, "T", RVSOFF, YELLOW, " BLITZ", CR
.byte RVSON, WHITE, "Y", RVSOFF, CYAN, " DEMON ATTACK", CR
.byte RVSON, WHITE, "U", RVSOFF, GREEN, " ATLANTIS", CR
.byte CR, " ", RVSON, WHITE, "SPACE", RVSOFF, YELLOW, " NEXT PAGE", CR
.byte BLUE
.byte $00
org $BFEE
game5:
sta $9C00
game4:
sta $9C00
game3:
sta $9C00
game2:
sta $9C00
game1:
sta $9C00
jmp copy_slap2 ; SYS 49149
incbin "Favorit_del_2.bin"
incbin "Favorit_del_3.bin"
incbin "games/Mole Attack(PAL_screen_position).bin" ; slot 3
incbin "games/The Sky is Falling(PAL_screen_fixed).bin" ; slot 4
incbin "games/Titan.bin" ; slot 5
incbin "games/Tank Atak(PAL_screen_position).bin" ; slot 6
incbin "games/Super Smash.bin" ; slot 7
incbin "games/Star Trek - S.O.S.bin" ; slot 8
incbin "games/Spiders of Mars.bin" ; slot 9
incbin "games/Satellites and Meteorites.PAL.bin" ; slot 10
incbin "games/Princess and Frog(PAL_screen_edit).bin" ; slot 11
incbin "games/Omega Race-orig(PAL_screen_position).bin" ; slot 12
incbin "games/Monster Maze.bin" ; slot 13
incbin "games/Jelly Monsters-fixed(PAL_screen_position).bin" ; slot 14
incbin "games/Choplifter-orig(PAL_screen_position).bin" ; slot 15
incbin "games/Tutankham.bin" ; slot 16
incbin "games/Paratrooper.bin" ; slot 17
incbin "games/Congo Bongo(PAL-screen_edit).bin" ; slot 18
incbin "games/Cosmic Jailbreak(PAL_screen_fixed).bin" ; slot 19
incbin "games/Galaxian.bin" ; slot 20
incbin "games/Jupiter Lander(PAL_screen_fixed).bin" ; slot 21
incbin "games/Pac-Man.bin" ; slot 22
incbin "games/Radar Rat Race(PAL_screen_fixed).bin" ; slot 23
incbin "games/Arcadia.bin" ; slot 24
incbin "games/Bank Robber.bin" ; slot 25
incbin "games/Dragonfire_EDIT.bin" ; slot 26
incbin "games/Demon Attack (EDIT).bin" ; first half of slot 27
incbin "games/Atlantis (EDIT).bin" ; second half of slot 27
Code: Select all
; Fredric Blåholtz
; Favorite games in a cartridge
; 2008
;
; dasm game.asm -f3 -ogame.bin to compile
processor 6502
dest = $1001 ; destination adress
org $a000
; ==============================================================
; Part 2 of favorite games, placed in block 1
; ==============================================================
copy_snk:
ldx #$07 ; number of 256 byte pages to copy
lda #<start_snk ; lower byte of address
sta $FB ; store in $00FB
lda #>start_snk ; upper byte of address
sta $FC ; store in $00FC
jsr copy_data
; Start program
jsr $C659 ; clr
jmp $C7AE ; run
copy_drv:
ldx #$07 ; number of 256 byte pages to copy
lda #<start_drv ; lower byte of address
sta $FB ; store in $00FB
lda #>start_drv ; upper byte of address
sta $FC ; store in $00FC
jsr copy_data
; Start program
jsr $C659 ; clr
jmp $C7AE ; run
copy_rkt:
ldx #$05 ; number of 256 byte pages to copy
lda #<start_rkt ; lower byte of address
sta $FB ; store in $00FB
lda #>start_rkt ; upper byte of address
sta $FC ; store in $00FC
jsr copy_data
; Start program
jsr $C659 ; clr
jmp $C7AE ; run
copy_tvu:
ldx #$07 ; number of 256 byte pages to copy
lda #<start_tvu ; lower byte of address
sta $FB ; store in $00FB
lda #>start_tvu ; upper byte of address
sta $FC ; store in $00FC
jsr copy_data
; Start program
jsr $C659 ; clr
jmp $C7AE ; run
copy_bui:
; set colors first
lda #25
sta $900F ; white+white
lda #$1F ; blue color
jsr $ffd2
ldx #$06 ; number of 256 byte pages to copy
lda #<start_bui ; lower byte of address
sta $FB ; store in $00FB
lda #>start_bui ; upper byte of address
sta $FC ; store in $00FC
jsr copy_data
; Start program
jsr $C659 ; clr
jmp $C7AE ; run
; ==============================================================
; Copy data, parameters already set
; ==============================================================
copy_data:
lda #<dest ; lower byte of address
sta $FD ; store in $00FD
lda #>dest ; upper byte of address
sta $FE ; store in $FE
loop2:
ldy #$00 ; Y = 0
loop1:
lda ($FB),Y ; A = contents of $00FB plus offset Y
sta ($FD),Y ; $00DF + offset Y = A
iny ; increase Y
bne loop1 ; Branch on Result not Zero to L1
inc $FC ; increase value at $00FC (upper byte of start address)
inc $FE ; increase value at $00FE (upper byte of dest. address)
dex ; X = X - 1 (decrease pages left to copy)
bne loop2 ; Branch on Result not Zero to L2
rts
; ==============================================================
; Game data
; ==============================================================
start_snk:
incbin "games/ormen-crunched.bin"
end_snk:
start_drv:
incbin "games/Driver!-crunch.bin"
end_drv:
start_rkt:
incbin "games/Rocket_Command-crunch.bin"
end_rkt:
start_tvu:
incbin "games/Tank_versus_Ufo-crunched.bin"
end_tvu:
start_bui:
incbin "games/Building-crunched.bin"
end_bui:
org $BFF1
; enters here for game 5
jmp copy_bui
; enters here for game 4
jmp copy_tvu
; enters here for game 3
jmp copy_rkt
; enters here for game 2
jmp copy_drv
; enters here for game 1
jmp copy_snk
Code: Select all
; Fredric Blåholtz
; Favorite games in a cartridge
; 2008
;
; dasm game.asm -f3 -ogame.bin to compile
processor 6502
dest = $1001 ; destination adress
org $a000
; ==============================================================
; Part 3 of favorite games, placed in block 2
; ==============================================================
copy_ski:
ldx #$09 ; number of 256 byte pages to copy
lda #<start_ski ; lower byte of address
sta $FB ; store in $00FB
lda #>start_ski ; upper byte of address
sta $FC ; store in $00FC
jsr copy_data
; Start program
jsr $C659 ; clr
jmp $C7AE ; run
copy_blz:
; clear screen
lda #$93
jsr $ffd2
; change to all white
lda #25
sta $900F
ldx #$11 ; number of 256 byte pages to copy
lda #<start_blz ; lower byte of address
sta $FB ; store in $00FB
lda #>start_blz ; upper byte of address
sta $FC ; store in $00FC
jsr copy_data
; Start program
jsr $C659 ; clr
jmp $C7AE ; run
; ==============================================================
; Copy data, parameters already set
; ==============================================================
copy_data:
lda #<dest ; lower byte of address
sta $FD ; store in $00FD
lda #>dest ; upper byte of address
sta $FE ; store in $FE
loop2:
ldy #$00 ; Y = 0
loop1:
lda ($FB),Y ; A = contents of $00FB plus offset Y
sta ($FD),Y ; $00DF + offset Y = A
iny ; increase Y
bne loop1 ; Branch on Result not Zero to L1
inc $FC ; increase value at $00FC (upper byte of start address)
inc $FE ; increase value at $00FE (upper byte of dest. address)
dex ; X = X - 1 (decrease pages left to copy)
bne loop2 ; Branch on Result not Zero to L2
rts
; ==============================================================
; Game data
; ==============================================================
start_ski:
incbin "games/Speedski-crunched.bin"
end_ski:
start_blz:
incbin "games/Blitz-crunched.bin"
end_blz:
org $BFF1
; enters here for game 5
jmp copy_ski
; enters here for game 4
jmp copy_ski
; enters here for game 3
jmp copy_ski
; enters here for game 2
jmp copy_blz
; enters here for game 1
jmp copy_ski
As you can see in part 0, some of the games added are modified, I took the liberty of changing the screen position to PAL by default on all games that weren't there from the beginning. I have also edited a few games because they unnecessarily wrote data in the I/O3 data area - which causes my latch to trig and change data - not good.
My thanks to carlsson, eslapion and 6502dude for all their aid in accomplishing this little miracle.
I've also copied some code from:
http://home.ica.net/~leifb/commodore/vi ... art-v7.asm
I hope this helps someone to build their own cart with their own favorites.
I'm up for questions, I'll post any updates to my build in this thread.
If someone has tips on how to calculate the values of the resistors and
capacitor connected to the input of the 74HC14 - that would be most welcome!