Vic 20 cartridge app. start problem.

You need an actual VIC.

Moderator: Moderators

Post Reply
HarryP2
Vic 20 Dabbler
Posts: 85
Joined: Sat Sep 26, 2015 8:40 am
Location: New York, U.S.A.

Vic 20 cartridge app. start problem.

Post by HarryP2 »

Hi! I am working on a Vic20 application cartridge setup for cc65 and am running into a problem. When I don't use puts(), it works. When I do use it, the emulator either resets itself on every screen refresh or locks up after the first screen refresh. The following is the start-up code for one configuration:
-----------------------------------
;
; 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 0;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()
inc $1E00
jmp *-3

;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
---------------------------------------------------
Can anybody find the problem?
User avatar
Radical Brad
Vic 20 Devotee
Posts: 256
Joined: Sat Jun 24, 2017 8:18 pm
Website: http://www.AtomicZombie.com
Location: Kakabeka Falls, ONT
Occupation: hACKER

Re: Vic 20 cartridge app. start problem.

Post by Radical Brad »

Having recently required this myself, I found this thread a few times in my searching, so I shall post my solution.

I think the code above actually "works", but simply recycles as the reset sequence keeps on looping back to the cartridge code.
What I did was pick through the Kernal ROM to extract what is required to initialize the system and start basic.
I added this to my cart startup, and then exit by calling the actual address where basic is then initialized and run.

My code also sets the VIC screen to yellow before staritng basic, so you can see that it is working.
I am using this as a stub for a Basic Wedge I am working on for another hardware project.
My Wedge will be hooking into address 776-777 to look for my new commands.

Warning, I do not use HEX and never will.
Assemble and save as an 8192 byte binary at location 40960...

Code: Select all


; ////////////////////////////////////////////////////////////////////////////////////////////
; ////////// JETPACK EXPANSION - KICKSTART CODE
; ////////////////////////////////////////////////////////////////////////////////////////////
; ////////// VERSION : JUL 10 2018
; ////////////////////////////////////////////////////////////////////////////////////////////

; START ADDRESS = 40969 @ 40960 TO 40961
 .ORG 40960
 .WORD 40969
 
; RESET ADDRESS = 40969 @ 40962 TO 40963
 .ORG 40962
 .WORD 40969
 
; BOOT CODE = a0CBM @ 40964 TO 40968
 .ORG 40964
 .BYTE 65,48,195,194,205
  
; PROGRAM START @ 40969 TO 49151
 .ORG 40969

; INITIALIZE INTERNAL RAM
 JSR 64909
 
; INITIALIZE IO VECTORS 
 JSR 64850
 
; INITIALIZE IO REGISTERS
 JSR 65017

; INITIALIZE VIC HARDWARE
 JSR 58648

; ENABLE INTERRUPTS   
 CLI
 
; TEST - YELLOW SCREEN
 lda #123
 sta 36879

; EXECUTE BASIC
 JMP 58232

Attach as a "Generic Cartridge Image" in Vice if that's how you roll.

Also note that since I am calling addresses in the Kernal directly, this only works on a VIC-20.
If Commodore ever comes back and releases a new VIC-20 and Kernal ROM, then I am screwed!
Risky, I know.

So there you have it.
The Kernal checks for the Cart Signature, turns over control, and then I do my own inisitialization calls, stuff in some wedge code, and then jump back to the Basic initialization routines.

Cheers,
Brad
Post Reply