Login
Forum Help



Post Your Message
="hidden" name="cat" value="Programming">
Username: (Login)

Topic:
Message:
 


Previous Messages
Posted By

Harry Potter
on 2025-05-10
10:46:42
 cc65/Plus4: two programs sometimes lock up displaying text

Hi! I have two programs written for the Plus4 using cc65 that use CBMSimpleIO, and both have the same program: while displaying text, they sometimes lock up. I don't know why. I pasted here some example code:

crt0.s
----------------------------
; ------------------------------------------------------------------------
; Constants

IRQInd = $500 ; JMP $0000 - used as indirect IRQ vector

; ------------------------------------------------------------------------
; Startup code

.segment "STARTUP"

Start:

; Save the zero-page locations that we need.

; sei ; No interrupts since we're banking out the ROM
; sta ENABLE_RAM
; ldx #zpspace-1
;L1: lda sp,x
; sta zpsave,x
; dex
; bpl L1
; sta ENABLE_ROM
; cli

; Switch to the second charset.

lda #14
jsr $FFD2 ; BSOUT

; Save some system stuff; and, set up the stack. The stack starts at the top
; of the usable RAM.

;tsx
;stx spsave ; Save system stk ptr

lda #<(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
ldx #>(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
sta sp
stx sp+1

; Set up the IRQ vector in the banked RAM; and, switch off the ROM.

ldx #<IRQ
ldy #>IRQ
sei ; No ints, handler not yet in place
sta ENABLE_RAM
stx $FFFE ; Install interrupt handler
sty $FFFF
cli ; Allow interrupts

; Clear the BSS data.

;jsr zerobss

; Initialize irqcount, which means that, from now on, custom linked-in IRQ
; handlers will be called (via condes).

; lda #.lobyte(__INTERRUPTOR_COUNT__*2)
; sta irqcount

; Call the module constructors.

;jsr initlib

; Push the command-line arguments; and, call main().

;jsr callmain
;jsr push0
;jsr push0
jsr _main

; Back from main() [this is also the exit() entry]. Run the module destructors.

_exit: ;pha ; Save the return code
;jsr donelib ; Run module destructors

; Disable the chained IRQ handlers.

; lda #0
; sta irqcount ; Disable custom IRQ handlers

; Copy back the zero-page stuff.

; ldx #zpspace-1
;L2: lda zpsave,x
; sta sp,x
; dex
; bpl L2

; Place the program return code into BASIC's status variable.

; pla
; sta ST

; Restore the stack pointer.

; ldx spsave
; txs

; Enable the ROM; and, return to BASIC.

sta ENABLE_ROM
;rts
jmp ($FFFC)

; ------------------------------------------------------------------------
; IRQ handler. The handler in the ROM enables the Kernal, and jumps to
; $CE00, where the ROM code checks for a BRK or IRQ, and branches via the
; indirect vectors at $314/$316.
; To make our stub as fast as possible, we skip the whole part of the ROM
; handler, and jump to the indirect vectors directly. We do also call our
; own interrupt handlers if we have any; so, they need not use $314.

.segment "LOWCODE"

IRQ: cld ; Just to be sure
; pha
; txa
; pha
; tya
; pha
; tsx ; Get the stack pointer
; lda $0104,x ; Get the saved status register
; and #$10 ; Test for BRK bit
; bne dobreak

; It's an IRQ; and, RAM is enabled. If we have handlers, call them. We will use
; a flag here instead of loading __INTERRUPTOR_COUNT__ directly, since the
; condes function is not reentrant. The irqcount flag will be set/reset from
; the main code, to avoid races.

; ldy irqcount
; beq @L1
; jsr callirq_y ; Call the IRQ functions

; Since the ROM handler will end with an RTI, we have to fake an IRQ return
; on the stack, so that we get control of the CPU after the ROM handler,
; and can switch back to RAM.

@L1: lda #>irq_ret ; Push new return address
pha
lda #<irq_ret
pha
php ; Push faked IRQ frame on stack
; pha ; Push faked A register
; pha ; Push faked X register
; pha ; Push faked Y register
sta ENABLE_ROM ; Switch to ROM
jmp (IRQVec) ; Jump indirect to Kernal IRQ handler

irq_ret:
sta ENABLE_RAM ; Switch back to RAM
; pla
; tay
; pla
; tax
; plp
rti

;dobreak:
; lda brk_jmp+2 ; Check high byte of address
; beq nohandler
; jmp brk_jmp ; Jump to the handler

; No break handler installed, jump to ROM.

;nohandler:
sta ENABLE_ROM
jmp ($FFFC) ; Jump indirect to the break vector
---------------------------
printc.s:
---------------------------
;Print return.
_printscr:
jsr _prints
_printcr:
lda #13
;jmp _printc
_printc:
;sta tmp4
;lda #$D2
;jmp callkernal
sta ENABLE_ROM
jsr $FFD2
sta ENABLE_RAM
rts
--------------------------
prints.s"
;Print return.
_printscr:
jsr _prints
_printcr:
lda #13
;jmp _printc
_printc:
;sta tmp4
;lda #$D2
;jmp callkernal
sta ENABLE_ROM
jsr $FFD2
sta ENABLE_RAM
rts
------------------
prints.s:
------------------
;Print a string of no more than 256 bytes using the kernal.
;As the routine is __fastcall__, the pointer already is in .X.A.
.proc _prints
sta ptr1 ;Store pointer.
stx ptr1+1
ldy #0 ;Start at offset 0.
@a:
lda (ptr1),y ;Load current char.
beq @exit ;Exit if null/EOS.
jsr _printc ;Print.
iny ;Advance until end of 256 bytes.
bne @a
@exit:
rts
.endproc

Copyright © Plus/4 World Team, 2001-2025. Support Plus/4 World on Patreon