Page 1 of 2

GenCartVic/cc65

Posted: Wed Nov 16, 2011 7:57 am
by Harry Potter
Hi. Harry Potter here. A couple years ago, I published on the cc65 contribs site a library called GenCartVic. It allows a programmer to create cartridge-based Vic-20 programs using cc65. It uses the keral start-up code and, therefore, can be used for applications. If you're interested, try it out.

GenCartVic How-To Help?

Posted: Fri Apr 15, 2016 6:46 am
by HarryP2
Hi! I'm wondering in maybe I'm approaching the issue the wrong way. If I wanted to create a cartridge-based application for the Vic20 that uses the kernal, how do I go about doing that?

Re: GenCartVic How-To Help?

Posted: Sat Apr 16, 2016 12:35 am
by tlr
There's a slight lack of details in your post, but: Just write a $a000 cartridge header + a small startup routine replicating the initial parts of the kernal reset routine found at $fd22, then go on with your code.

Re: GenCartVic How-To Help?

Posted: Sat Apr 16, 2016 2:07 am
by srowe
I'm guessing you know that you provide
  • a cold start routine
  • a warm start routine
The cold start routine is called quite early in the boot process and there's no equivalent of the RAMTAS, IOINIT routines that the C64 has. The KERNAL code that is run for a normal BASIC start is

Code: Select all

FRESTOR  = $FD52
INITMEM  = $FD8D
INITVIA  = $FDF9
INITSK   = $E518

JSR	INITMEM       ; initialise and test RAM
JSR	FRESTOR       ; restore default I/O vectors
JSR	INITVIA       ; initialise I/O registers
JSR	INITSK        ; initialise hardware
CLI                 ; enable interrupts
followed by a jump to the BASIC cold start vector.

The warm start routine is called with .A, .X and .Y (top) on the stack, you must not use RTI to exit your routine. The KERNAL routine at $FF56 can restore the registers and return.

Re: GenCartVic How-To Help?

Posted: Sat Apr 16, 2016 4:25 am
by HarryP2
Swore: I thank you for your input. Now, I'm wondering if I am doing the warm-start wrong. Will the wrong warm-start address cause the symptoms? How do I write the warm-start routine?

Re: GenCartVic How-To Help?

Posted: Sat Apr 16, 2016 4:30 am
by HarryP2
tlr wrote:There's a slight lack of details in your post, but: Just write a $a000 cartridge header + a small startup routine replicating the initial parts of the kernal reset routine found at $fd22, then go on with your code.
I do that. The problem is when I use cc65's puts() routine. When I use it, I experience the problems. When I use my CBMSimpleIO library instead, I don't, and I'm wondering why. Now, cc65's puts() function seems to open some files (screen and keyboard) upon initialization.

Re: GenCartVic How-To Help?

Posted: Sat Apr 16, 2016 4:36 am
by srowe
HarryP2 wrote:Now, I'm wondering if I am doing the warm-start wrong. Will the wrong warm-start address cause the symptoms? How do I write the warm-start routine?
Depends what your symptoms are. A bogus warm start routine could be called on the jiffy timer expiry and cause the system to lockup. If you're not needing to intercept STOP/RESTORE you could try using the normal routine at $FEC7.

Re: GenCartVic How-To Help?

Posted: Sat Apr 16, 2016 4:47 am
by HarryP2
srowe wrote:
HarryP2 wrote:Now, I'm wondering if I am doing the warm-start wrong. Will the wrong warm-start address cause the symptoms? How do I write the warm-start routine?
Depends what your symptoms are. A bogus warm start routine could be called on the jiffy timer expiry and cause the system to lockup. If you're not needing to intercept STOP/RESTORE you could try using the normal routine at $FEC7.
What you describe are exactly my symptoms. Now, I thank you for your input. :) I'll try it now.

Re: GenCartVic How-To Help?

Posted: Sat Apr 16, 2016 4:52 am
by HarryP2
I just realized: I can't access the source code:it's on a floppy, and my laptop's USB floppy drive is broken. :( I have to go to my mother's house and pick up a working one.

Re: GenCartVic How-To Help?

Posted: Sat Apr 16, 2016 5:08 am
by groepaz
There's a slight lack of details in your post
for example "i screwed up the crt0 and now things dont work as expected" 8)

Re: GenCartVic How-To Help?

Posted: Sat Apr 16, 2016 5:38 am
by HarryP2
Okay. I tried the vector on an old copy. Same problem. :( Following is the crt0.s file I'm using:

Code: Select all

;
; Startup code for cc65 (Vic20 version)
;

	.export		_exit
        .export         __STARTUP__ : absolute = 1      ; Mark as startup
	.import		initlib, donelib, callirq
       	.import	       	zerobss, push0
	.import	     	_main
        .import         RESTOR, BSOUT, CLRCH
	.import	       	__INTERRUPTOR_COUNT__
     	.import		__RAM_START__, __RAM_SIZE__	; Linker generated

	.import		__DATA_LOAD__, __DATA_RUN__, __DATA_SIZE__
	
	.import		_puts, _cgetc, _memcpy, pushax

        .include        "zeropage.inc"
     	.include     	"vic20.inc"

PLOT=$FFF0
; ------------------------------------------------------------------------
; Place the startup code in a special segment.

.segment       	"STARTUP"


	.word	$A000			;Cartridge load address
	.word	Crt0_Init		;Address of start-up code
	.word	$FEC7;Crt0_Start		;I don't know.
	.byte	$41,$30,$C3,$C2,$CD	;ROM present signature

;--------------------------------------------------------------------
;Startup code:
Crt0_Init:
sei
	cld
	ldx	#$ff
	txs
	
;Run kernal setup routines.
jsr	$FD8D
jsr	$FD52
jsr	$FDF9
jsr	$E518
cli
;Set up BASIC env.

jsr	$E3A4

;Set up stack.
	;Clear bss.

; Save system stuff and setup the stack

	lda    	#<$1E00
	sta	sp
	lda	#>$1E00
       	sta	sp+1   		; Set argument stack ptr

	;jsr	zerobss

	;Copy read/write data to RAM.
	lda	#<__DATA_RUN__
	ldx	#>__DATA_RUN__
	jsr	pushax
	lda	#<__DATA_LOAD__
	ldx	#>__DATA_LOAD__
	jsr	pushax
	lda	#<__DATA_SIZE__
	ldx	#>__DATA_SIZE__
	;jsr	pushax
	jsr	_memcpy


	;jsr	CLRCH
; Switch to second charset

	lda	#14
	jsr	BSOUT

	;ldx	#0
	;ldy	#0
	;clc
	;jsr	PLOT
	
	;lda	#65
	;jsr	$FFD2
; Clear the BSS data

	;jsr	zerobss

;Call constructors.
	;jsr	initlib

; If we have IRQ functions, chain our stub into the IRQ vector

        lda     #<__INTERRUPTOR_COUNT__
      	beq	NoIRQ1
      	lda	IRQVec
       	ldx	IRQVec+1
      	sta	IRQInd+1
      	stx	IRQInd+2
      	lda	#<IRQStub
      	ldx	#>IRQStub
      	sei
      	sta	IRQVec
      	stx	IRQVec+1
      	cli

; Call module constructors

NoIRQ1: jsr     initlib

; Push arguments and call main()

        ;jsr     callmain
	jsr	push0
	jsr	push0
	jsr	_main

; Back from main (This is also the _exit entry). Run module destructors

_exit:  jsr     donelib

; Reset the IRQ vector if we chained it.

        ;pha  		     	; Save the return code on stack
	lda     #<__INTERRUPTOR_COUNT__
	beq	NoIRQ2
	lda	IRQInd+1
	ldx	IRQInd+2
	sei
	sta	IRQVec
	stx	IRQVec+1
	cli


NoIRQ2:
; Place the program return code into ST

	;pla
	;sta	ST

;End and restart.
;Print end message.
	lda	#<EndMsg
	ldx	#>EndMsg
	
	jsr	_puts
;Wait for key.
	jsr	_cgetc
;Restart.
	jmp	($FFFC)		;Kernal reset vector

; ------------------------------------------------------------------------
; The IRQ vector jumps here, if condes routines are defined with type 2.

IRQStub:
	cld    	       		   	; Just to be sure
       	jsr    	callirq                 ; Call the functions
       	jmp    	IRQInd			; Jump to the saved IRQ vector

; ------------------------------------------------------------------------
; Data

.data

IRQInd: jmp     $0000
.rodata
;End message.
EndMsg:
	.byt	147,"Your program ended.",13
	.byt	"Press any key to", 13
	.byt	"restart.",0
And the .cfg:

Code: Select all

SYMBOLS {
    __STACKSIZE__: value = $200, type = weak;	# 512-byte stack
}
MEMORY {
    ZP: start =  $0002, size = $001A, type = rw, define = yes;
    #RAM: start = $0200, size = $0200, define = yes;
    RAM: start = $1000, size = $0C00, define = yes;
    ROM: start = $9FFE, size = $2002, define = yes, file = %O,
	 fill=yes;
}
SEGMENTS {
    STARTUP:  load = ROM, type = ro;
    LOWCODE:  load = ROM, type = ro,               optional = yes;
    INIT:     load = ROM, type = ro, define = yes, optional = yes;
    CODE:     load = ROM, type = ro;
    RODATA:   load = ROM, type = ro;
    DATA:     load = ROM, run = RAM, type = rw, define = yes;
    #ZPSAVE:   load = RAM, type = bss;
    BSS:      load = RAM, type = bss, define = yes;
    HEAP:     load = RAM, type = bss, optional = yes; # must sit just below stack
    ZEROPAGE: load = ZP,  type = zp;
}
FEATURES {
    CONDES: segment = INIT,
	    type = constructor,
	    label = __CONSTRUCTOR_TABLE__,
	    count = __CONSTRUCTOR_COUNT__;
    CONDES: segment = RODATA,
	    type = destructor,
	    label = __DESTRUCTOR_TABLE__,
	    count = __DESTRUCTOR_COUNT__;
    CONDES: segment = RODATA,
	    type = interruptor,
	    label = __INTERRUPTOR_TABLE__,
	    count = __INTERRUPTOR_COUNT__;
}
Does this help?

Re: GenCartVic How-To Help?

Posted: Sat Apr 16, 2016 5:45 am
by Mike
...

Re: GenCartVic How-To Help?

Posted: Wed Apr 20, 2016 11:48 am
by brain
I've been following this (and related) threads for some time, as I am a C developer and I have not had any luck getting cc65 to produce a valid $a000 cart image. I even had Oliver (I think that's his name) who maintains the compiler try to help, but neither of us could get the simple "hello world" to work.

SO, is there a working hellow world $a000 cart image project I could peruse? I was using 2.14 of cc65, as I recall, and I was able to get c64 cart images to compile fine

I also created (or maybe I borrowed some code, not sure) and successfully created a working 8kB VIC app image and then extended it to be a 16kB image. But. both fo those relied on loading into start of RAM and running from there,

Jim

Re: GenCartVic How-To Help?

Posted: Wed Apr 20, 2016 5:42 pm
by HarryP2
Well, my cartridge cfg. seems to work with CBMSimpleIO but not the stdio library. Also, I've at one time been able to start working on a Vic20 game cartridge library but dumped it fearing cc65 C would be too slow for it and the Vic20 didn't have enough memory for that type of game. I can try to look for the CRT0.S file for the latter if you're interested. :)

Re: GenCartVic How-To Help?

Posted: Wed Apr 20, 2016 8:33 pm
by brain
That would be very helpful.

Jim