Jump to content
  • 0

Console Kernal addresses inconsistency


Fippy
 Share

Question

Hey all,

First attempt at getting some text on the screen in 6502. I notice inconsistencies between the Programmers Reference Guide and some of Matt H.'s videos. Example:

CHROUT = $FEDE  or $FFD2
CHRIN  = $FEE1  or $FFCF

I've seen 2 values for each of these. I've also seen both values in the videos.

In the videos there's mention of PLOT, SCREEN, clear screen and GETIN, and none of these seem to exist in the Programmers Reference Guide. Do those kernal routines exist still? I hope so.

Also, any attempt I make to display characters results in garbage characters. See sample assembly below.

Using:

cl65 -t cx16 -o HELLOWORLD.PRG -l listing.map *.asm

./x16emu_mac-r38/x16emu -prg helloworld.PRG

I also notice that in memory, the "Hello" appears as ?ELLO, which is peculiar, making me suspect it doesn't know about PETSCI?

Thanks for any help,

Fippy

 

Quote

 

.org $080D

.segment "STARTUP"
.segment "INIT"
.segment "ONCE"
.segment "CODE"

CHROUT = $FFD2
CHRIN  = $FFCF

ZP_PTR_0 = $20

message:
  .byte "Hello",0

start:
  lda #<message
  sta ZP_PTR_0
  lda #>message
  sta ZP_PTR_0 + 1
  ldy #0
@loop:
  lda (ZP_PTR_0),y
  beq stop
  JSR CHROUT
  iny
  bra @loop
stop:
  rts

 


 

Link to comment
Share on other sites

6 answers to this question

Recommended Posts

  • 0

Hi,

Some pointers:

  • Lose the .org and .segment statements, they are not needed
  • The message string cannot be at the beginning of the source code if you intend to use $080d as entry point. The computer doesn't know if the bytes there are a string or code, it will try to run it as code, and the program likely crashes. Move the string to the end of the source.
  • To compile I use the following command: cl65 -o HELLOWORLD.PRG -u __EXEHDR__ -t cx16 -C cx16-asm.cfg helloworld.asm
  • The compiler translates ASCII to PETSCII correctly, but note that an unshifted char in your modern PC will be an uppercase char on the X16, presuming you are using the default uppercase/graphics mode that the X16 is started in.

The modified source code that I tested (lines that could be removed commented out):

;.org $080D
 
;.segment "STARTUP"
;.segment "INIT"
;.segment "ONCE"
.segment "CODE"
 
CHROUT = $FFD2
;CHRIN = $FFCF
 
ZP_PTR_0 = $20
 
start:
lda #<message
sta ZP_PTR_0
lda #>message
sta ZP_PTR_0 + 1
ldy #0
@loop:
lda (ZP_PTR_0),y
beq stop
JSR CHROUT
iny
bra @loop
stop:
rts
 
message:
.byte "hello",0
Edited by Stefan
Link to comment
Share on other sites

  • 0

If you are using cl65, the .org and . segment statements are required, or the build will fail. The discrepancy between the addresses is because of the RAM vector that the Kernal uses.

In the case of CHROUT, the suggested address to use is $FFD2. What this will do is is jump to the address stored in RAM at $0326. By default, that address is $FEDE back in the ROM, so you could just JSR to there directly if you want to ensure you are calling the ROM routine instead of a custom one that has been injected into the RAM vector. A lot of the Kernal routines work like this.

Edited by SlithyMatt
Link to comment
Share on other sites

  • 0

Ah. Thanks for the replies folks!

So is it best practice to call $FFD2, or the ram vector itself, or the actual default address at $FEDE?

Also, do the other Kernal functions like PLOT, clear screen etc still exist? They were in your videos, Matt, but not in the Reference Manual.

 

Link to comment
Share on other sites

  • 0

.org and .segment statements are not required if you compile with the config file cx16-asm.cfg.

If using the command line params I mentioned, the compiler defaults to the CODE segment, and you therefore need not explicitly tell the compiler that.

The .org will, surprisingly, not affect the load address of the executable. It sets the program counter, normally only used when you compile code that is meant to be moved to its final destination after the program is loaded. As the manual says, you normally need not use the .org statement (https://www.cc65.org/doc/ca65-11.html#ss11.72)

In most cases you want to create a program that can be run with the BASIC RUN command. To do this, use the  -u __EXEHDR__ compiler param, and all will be done automatically for you.

As proof of this, the source code, and the command line params given to cl65 in my previous post works fine.

If you want to manually control where code ends up in memory when you load the executable, you must learn how to use and write CA65 config files.

You can test writing a small program using the .org statement, for instance this:

.segment "STARTUP"
.segment "INIT"
.segment "ONCE"
.segment "BASS"
.segment "CODE"
 
.org $0900
 
lda #65
jsr $ffd2
rts

Compile it with "cl65 -t cx16 -o TEST.PRG test.asm". Move the program to the SD card image. Load the program it in the emulator with LOAD"TEST.PRG",8,1. The program still loads to $0801.

This is because the CA65 has a linker that decides where the code ends up. And to give the linker commands, you need to write config files.

Edited by Stefan
Link to comment
Share on other sites

  • 0
3 hours ago, Fippy said:

Ah. Thanks for the replies folks!

So is it best practice to call $FFD2, or the ram vector itself, or the actual default address at $FEDE?

Also, do the other Kernal functions like PLOT, clear screen etc still exist? They were in your videos, Matt, but not in the Reference Manual.

 

Best practice is whatever is best for your program. The thing about the eventual ROM address is that it's subject to change, whereas the address that jumps to the RAM vector is set in stone, as CHROUT is $FFD2 in the C64, too, as is the location of the RAM vector. But if you really need to shave some cycles, you can hotwire your code at the risk of it breaking after a ROM upgrade.

Most of the C64 Kernal is in the X16 Kernal, with only a few non-applicable routines left out. The Programmer's Guide in the x16-docs repo documents all of that, including the addresses for them in the ROM. You will need to refer to C64 docs to know how each of them works until the X16 docs are completed.

Link to comment
Share on other sites

  • 0
On 8/28/2021 at 11:19 AM, Fippy said:

Ah. Thanks for the replies folks!

So is it best practice to call $FFD2, or the ram vector itself, or the actual default address at $FEDE?

Also, do the other Kernal functions like PLOT, clear screen etc still exist? They were in your videos, Matt, but not in the Reference Manual.

 

I downloaded pdfs of both the VIC-20 and C64 reference manuals. The VIC-20 one is particularly useful for the oldest Kernal routines, like CHROUT and GETIN and PLOT. The X16 manual only covers news stuff specific to the X16. 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

Please review our Terms of Use