a BASIC game as cartridge

Modding and Technical Issues

Moderator: Moderators

User avatar
Mike
Herr VC
Posts: 4840
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

a BASIC game as cartridge

Post by Mike »

These days I delved into hardware hacking. :)

With Schema's method I successfully converted one of my games (TRON Light Cycles) into cartridge format. I had a leftover Personal Finance cartridge handy, onto which I crossed the lines A11 and A12, and then replaced the ROM chip with a programmed 2732 EPROM:

Image

Image

This method is a slightly unusual way to drive the EPROM: A12 drives CS, and that line is active low on the lower half of each 8K block. Oh well. And the BLK5 signal (which normally is tied to CS) drives OE instead. And A11 ends up at the right pin. It just happens to function. ;)

Since EPROM burner (at work) and VIC-20 (at my parents home) are away at ~600 km distance, everything needed to be correct. At least I could test the cartridge image within VICE. As regards hardware, I had only one try. Surely enough, it works!

This is the code I use to start the BASIC program in the cartridge. Most of it is copied from the RESET routine, with some alterations, to make it insensitive to RAM expansions. Also STOP and STOP/RESTORE are disabled. It can be easily adjusted for programs up to 3.5K length.

Greetings,

Michael

Edit: Here's the EPROM image for download (link). To run it in VICE, attach it at $A000 and press Alt+R.

Code: Select all

>A000  10 A0                 ; Reset Vector
>A002  09 A0                 ;   NMI Vector
>A004  41 30 C3 C2 CD        ; A0CBM Signature

.A009  2C 11 91  BIT $9111   ; Acknowledge NMI
.A00C  4C 56 FF  JMP $FF56   ; End NMI
.A00F  EA        NOP
.A010  20 8D FD  JSR $FD8D   ; RAMTAS
.A013  A9 10     LDA #$10    ; Force BASIC into
.A015  8D 82 02  STA $0282   ; unexpanded RAM
.A018  A9 1E     LDA #$1E    ; ...
.A01A  8D 84 02  STA $0284   ; ...
.A01D  8D 88 02  STA $0288   ; ...
.A020  20 52 FD  JSR $FD52
.A023  A9 C2     LDA #$C2    ; Disable
.A025  8D 14 03  STA $0314   ; STOP key
.A028  20 F9 FD  JSR $FDF9
.A02B  20 18 E5  JSR $E518
.A02E  58        CLI
.A02F  20 5B E4  JSR $E45B
.A032  20 A4 E3  JSR $E3A4
.A035  A2 FB     LDX #$FB
.A037  9A        TXS
.A038  A9 00     LDA #$00    ; *disable* OS messages
.A03A  20 90 FF  JSR $FF90   ; (-> program mode)
.A03D  A9 00     LDA #$00    ; Copy from ...
.A03F  A8        TAY
.A040  85 FB     STA $FB
.A042  85 FD     STA $FD
.A044  A9 A8     LDA #$A8    ; &A800 to ...
.A046  85 FC     STA $FC
.A048  A9 10     LDA #$10    ; &1000 ...
.A04A  85 FE     STA $FE
.A04C  A2 08     LDX #$08    ; ... 8 pages.
.A04E  B1 FB     LDA ($FB),Y
.A050  91 FD     STA ($FD),Y
.A052  C8        INY
.A053  D0 F9     BNE $A04E
.A055  E6 FC     INC $FC
.A057  E6 FE     INC $FE
.A059  CA        DEX
.A05A  D0 F2     BNE $A04E
.A05C  A9 B4     LDA #$B4    ; End of program a.k.a.
.A05E  85 2D     STA $2D     ; start of variables at
.A060  A9 17     LDA #$17    ; &17B4
.A062  85 2E     STA $2E
.A064  20 59 C6  JSR $C659   ; CLR, reset TXTPTR
.A067  4C AE C7  JMP $C7AE   ; Execute next statement
                             ; ("RUN")
Last edited by Mike on Thu Feb 20, 2014 6:25 pm, edited 2 times in total.
User avatar
eslapion
ultimate expander
Posts: 5458
Joined: Fri Jun 23, 2006 7:50 pm
Location: Canada
Occupation: 8bit addict

Re: a BASIC game as cartridge

Post by eslapion »

Mike wrote:It can be easily adjusted for programs up to 3.5K length.
Since I assume the programs code runs in BLK5 and the variables are put in RAM then why would it not be possible to run a program of 7k ?
6502dude
megacart
Posts: 1581
Joined: Wed Dec 01, 2004 9:53 am

Post by 6502dude »

I believe the size limit, in the set up above, is based on the 2732 Eprom Mike used.

With A12 available on edgecard (not always present on lower end carts), the board could be hacked to accomodate a 2764
Image Mega-Cart: the ultimate cartridge for your Commodore Vic-20
User avatar
Schlowski
NoMess!
Posts: 892
Joined: Tue Jun 08, 2004 12:20 pm

Post by Schlowski »

Mike copies the program from EPROM to RAM, therefore the BASIC program is running in the unexpanded RAM space of the VIC. (See comments in his listing)
It would require a different setup to make BASIC think it's RAM is starting at BLK 5.

And afaik it is required that variables etc. start after the BASIC program, i.e. it is not possible to have the BASIC program in BLK 5 in a ROM and only set the pointers for variables etc. to RAM. But since I did not dig into my ROM listings for this I could be totally wrong :-)

Björg
Boray
Musical Smurf
Posts: 4064
Joined: Mon May 03, 2004 10:47 am

Post by Boray »

I think it's possible to run a basic program in block 5 and have all of the ram for variables. But you have to relink the line numbers for block 5 and set the appropriate pointers. Not 100% sure, but I think that works...
PRG Starter - a VICE helper / Vic Software (Boray Gammon, SD2IEC music player, Vic Disk Menu, Tribbles, Mega Omega, How Many 8K etc.)
User avatar
Schlowski
NoMess!
Posts: 892
Joined: Tue Jun 08, 2004 12:20 pm

Post by Schlowski »

Wasn't there a problem with the BASIC interpreter which expects the start of variables at BASIC program end? I seem to remember that you cannot set start of variables <> end of BASIC program.
Boray
Musical Smurf
Posts: 4064
Joined: Mon May 03, 2004 10:47 am

Post by Boray »

I do that with the vic-menu. There is a ML program between the basic program and the variables.
PRG Starter - a VICE helper / Vic Software (Boray Gammon, SD2IEC music player, Vic Disk Menu, Tribbles, Mega Omega, How Many 8K etc.)
User avatar
Schlowski
NoMess!
Posts: 892
Joined: Tue Jun 08, 2004 12:20 pm

Post by Schlowski »

But to do that you have to set end of Basic program = end of ML program, right? Otherwise Basic would overwrite your ML program with the first usage of a variable.

What makes me wonder is that regarding to the following ZP-addresses you have only one pointer which both is end of Basic program and start of variables (44,45). At least you shouldn't be allowed to make a CLR which definately sets 44/45 to end of Basic - and this would be in ROM...
*002B-002C 43-44 Pointer: Start of Basic
*002D-002E 45-46 Pointer: Start of Variables
*002F-0030 47-48 Pointer: Start of Arrays
*0031-0032 49-50 Pointer: End of Arrays
*0033-0034 51-52 Pointer: String storage (moving down)
User avatar
Schlowski
NoMess!
Posts: 892
Joined: Tue Jun 08, 2004 12:20 pm

Post by Schlowski »

Ok, I tried the following in VICE:

1. Set RAM to Unexpanded+BLK 5
2. POKE 44,160 (=Start of BASIC at $A000)
3. Enter 10 ?"TEST" + return
-> Freeze

1. Set RAM to Unexpanded+BLK 5
2. Poke 44,160 (=Start of BASIC at $A000)
3. NEW
4. Enter 10 ?"TEST" + return
-> OUT OF MEMORY

1. Set RAM to Unexpanded+BLK 5
2. POKE 44,160 (=Start of BASIC at $A000)
3. NEW
4. POKE 46,16:POKE48,16:POKE50,16:POKE52,30 (Set pointers for variables etc. like unexpanded configuration)
5. Enter 10 ?"TEST" + return
-> garbage on screen, looks like the pointer to the video matrix got wild...

So what one can do to move the BASIC start up, for example for making space for UDF's etc. seems not to work if it 'overtakes' the variable pointers... Maybe with some more kernal calls...
carlsson
Class of '6502
Posts: 5516
Joined: Wed Mar 10, 2004 1:41 am

Post by carlsson »

This one works:

1. Set RAM to unexpanded + BLK5
2. POKE44,160:POKE40960,0:POKE56,192:NEW
3. Enter your program:

10 DIMA$(10):FORI=1TO10
15 PRINT"NAME #";I:INPUT"YOUR NAME";A$(I)
20 NEXT:FORI=1TO10
25 PRINTA$(I):NEXT

4. POKE45,3:POKE46,16:POKE56,30:CLR (the other values follow)

Voila! 3581 bytes free, and a Basic program in memory that is fully runnable (but not editable!)

Since the program on the cartridge is already written when you boot the computer, you don't need to have the pointers set in odd directions while you input the program, only when you run it.
Anders Carlsson

Image Image Image Image Image
User avatar
Schlowski
NoMess!
Posts: 892
Joined: Tue Jun 08, 2004 12:20 pm

Post by Schlowski »

Ah, I should have had a better look at my ZP table
*002B-002C 43-44 Pointer: Start of Basic
*002D-002E 45-46 Pointer: Start of Variables
*002F-0030 47-48 Pointer: Start of Arrays
*0031-0032 49-50 Pointer: End of Arrays
*0033-0034 51-52 Pointer: String storage (moving down)
0035-0036 53-54 Utility string pointer
*0037-0038 55-56 Pointer: Limit of memory

* useful memory locations
I just didn't realized 55/56, how foolish ;-)
carlsson
Class of '6502
Posts: 5516
Joined: Wed Mar 10, 2004 1:41 am

Post by carlsson »

Yes, but the main point I tried to make was that you're not supposed to enter a Basic program with start of Basic pointing at one place and start of variables (i.e. end of program) pointing elsewhere. Once the program is in place and all line numbers happily linked, you can point start of variables elsewhere.
Anders Carlsson

Image Image Image Image Image
User avatar
Schlowski
NoMess!
Posts: 892
Joined: Tue Jun 08, 2004 12:20 pm

Post by Schlowski »

Good point, was just distracted from the original problem by trying to get this running...
User avatar
Mike
Herr VC
Posts: 4840
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Post by Mike »

Since the original program was designed to run in the unexpanded VIC, I really didn't think about running it from ROM. For bigger programs however, your ideas are a big improvement!

The copy routine can be omitted entirely, and the ML section that sets the start of variables is replaced by a write to the ZP pointer containing the start-address of the program:

Code: Select all

>A000  10 A0                 ; Reset Vector 
>A002  09 A0                 ;   NMI Vector 
>A004  41 30 C3 C2 CD        ; A0CBM Signature 

.A009  2C 11 91  BIT $9111   ; Acknowledge NMI 
[...] ; up to here identical code.
.A03A  20 90 FF  JSR $FF90   ; (-> program mode) 
.A03D  A9 01     LDA #$01    ; Start of program at ($A101)
.A03F  85 2B     STA $2B
.A041  A9 A1     LDA #$A1
.A043  85 2C     STA $2C
.A045  20 59 C6  JSR $C659   ; CLR, reset TXTPTR 
.A048  4C AE C7  JMP $C7AE   ; Execute next statement 
                             ; ("RUN")
An additional idea:

These ROM stored BASIC programs can be used without destroying the current BASIC program. If they are executed, all that is need to be done is:

- read the original contents of $2B/$2C and store them away.
- install a handler on ($0302) (BASIC warm start)
- set address $2B/$2C to the ROM BASIC program and run it.
- when the ROM program ends, let the handler at ($0302) restore the original contents of $2B/$2C

The ROM program would then use the same space for variables as the RAM based program. And no-one expects the variables to be permanent. :)

Michael
User avatar
Schema
factor
Posts: 1430
Joined: Tue Mar 23, 2004 7:07 am
Website: http://www.jammingsignal.com
Location: Toronto, Ontario

Re: a BASIC game as cartridge

Post by Schema »

Mike wrote: This method is a slightly unusual way to drive the EPROM: A12 drives CS, and that line is active low on the lower half of each 8K block. Oh well. And the BLK5 signal (which normally is tied to CS) drives OE instead. And A11 ends up at the right pin. It just happens to function.
Yeah, it was a bit of a hack. I took 6502dude's original method of quickly modding cartridges, which mirrored the 4K ROMs into both halves, and added A12 so that the cart would play nicely with the Super Expander (I think?) which sits in the upper half of Block 3.
Post Reply