KERNAL CRC call (not sure if right)

All aspects of programming on the Commander X16.
Eirik Stople
Posts: 14
Joined: Thu Jun 04, 2020 8:57 pm

Re: KERNAL CRC call (not sure if right)

Post by Eirik Stople »

The "bootloader missing" is due to 512 bytes of 0xFF, giving that checksum. You may have installed the latest SMC firmware using an external programmer, and installed the .hex file without the bootloader, which will give this result. But I guess it is more likely that you have SMC firmware 47.0.0 or earlier, which have not implemented the flash read functionality, causing all I2CPEEK to read FF instead of the actual contents of flash.
Xiphod
Posts: 595
Joined: Thu Apr 15, 2021 8:05 am

Re: KERNAL CRC call (not sure if right)

Post by Xiphod »

Eirik Stople wrote: Thu Jan 09, 2025 11:48 pm You may have installed the latest SMC firmware using an external programmer, and installed the .hex file without the bootloader, which will give this result.
Actually this is right, for that particular system yes I think we had used an external programmer.
Xiphod
Posts: 595
Joined: Thu Apr 15, 2021 8:05 am

Re: KERNAL CRC call (not sure if right)

Post by Xiphod »

Below is code used to directly make the equivalent CRC16 call against the same 4-byte data sequence ($01 $02 $03 $04). The result is still coming out as $6122, while other sources are saying the CRC16 result under these conditions should get computed as $89C3. That's conditions of starting with a CRC of $FFFF, using a Poly of $1021

The code below is POKE'd into $0500 (golden RAM region), then executed. That POKE'd code sets up the CRC16 call inputs at $0400 (the 4-byte data stream).
 

Code: Select all

20 AO=$0500 : A=AO
30 READ V:IF V=-1 THEN GOTO 60
40 POKE A,V:A=A+1
50 GOTO 30
60 SYS AO
65 PRINT HEX$(PEEK(7)*256+PEEK(6))
66 PRINT HEX$(PEEK($A000)*256+PEEK($A001)) : REM CONFIRM BACKUP OF R2 IS SAME
70 END
1000 DATA  $A9, $01       : REM               LDA $01
1010 DATA  $8D, $00, $04  : REM               STA $0400
1020 DATA  $A9, $02       : REM               LDA $02
1030 DATA  $8D, $01, $04  : REM               STA $0401
1040 DATA  $A9, $03       : REM               LDA $03
1050 DATA  $8D, $02, $04  : REM               STA $0402
1060 DATA  $A9, $04       : REM               LDA $04
1070 DATA  $8D, $03, $04  : REM               STA $0403
1080 : REM   LET R0=$0400 (ADDR) R1=$0004 (BYTES)
1090 DATA  $A9, $00       : REM               LDA #$00
1100 DATA  $85, $02       : REM               STA $02   R0.LO
1110 DATA  $A9, $04       : REM               LDA #$04
1120 DATA  $85, $03       : REM               STA $03   R0.HI
1130 DATA  $A9, $04       : REM               LDA #$04
1140 DATA  $85, $04       : REM               STA $04   R1.LO
1150 DATA  $A9, $00       : REM               LDA #$00
1160 DATA  $85, $05       : REM               STA #$05  R1.HI
1170 DATA  $20, $EA, $FE  : REM               JSR $FEEA  CALC CRC
1172 DATA  $A5, $06       : REM LDA $06    MAKE A COPY OF ADDR 6 AND 7 (R2) BEFORE RETURN TO BASIC
1173 DATA  $8D, $01, $A0  : REM STA $A001
1174 DATA  $A5, $07       : REM LDA $07
1175 DATA  $8D, $00, $A0  : REM STA $A000
1180 DATA  $60            : REM             RTS
1190 DATA  -1
Stefan
Posts: 466
Joined: Thu Aug 20, 2020 8:59 am

Re: KERNAL CRC call (not sure if right)

Post by Stefan »

I got the same result (0x6122) when calling the Kernal CRC function. I also tried to write my own small assembly routine, but the outcome was the same.

Eirik has been able to use the Kernal function successfully in the SMC tools he made.

It needs some further checking.
Stefan
Posts: 466
Joined: Thu Aug 20, 2020 8:59 am

Re: KERNAL CRC call (not sure if right)

Post by Stefan »

I just checked the Kernal source code.

There're two loops that reads the input, one if the byte count is less than 256 bytes, and one if its 256 bytes ore more.

As far as I can tell, the loop that handles a byte count below 256, reads the input backwards. And sure enough, if you give it the input in the form [4, 3, 2, 1], it returns the expected result 0x89c3.
Xiphod
Posts: 595
Joined: Thu Apr 15, 2021 8:05 am

Re: KERNAL CRC call (not sure if right)

Post by Xiphod »

Oh wow! And the SMC bootloader is 512 bytes, right? So this doesn't appear there.

Well, very interesting. Thanks for taking time to check. I had poked around in the KERNAL and just missed that, so good find! I'll setup a 300 byte test and double check, but yep sounds like this is it. Once confirmed, I'll try to suggest an update the X16 Tech Ref, since that's an important and subtle tip.
EDIT: Oh, BASIC strings can't be over 256 bytes. RIP. Ok, will set up the test differently.

Curious about the rationale on different behavior below 256 bytes, but I know in some CRC implementations online they do have an input parameter asking about "Reverse" or not.

Actually this will be important to me. If someone wants to transfer say a 128 byte file, the sender now has to know to embed the CRC header differently. Or guess I could require a pad to say 300 bytes and trim it to actual size (128 or whatever) in the receive side.
Last edited by Xiphod on Fri Jan 10, 2025 9:06 am, edited 1 time in total.
Eirik Stople
Posts: 14
Joined: Thu Jun 04, 2020 8:57 pm

Re: KERNAL CRC call (not sure if right)

Post by Eirik Stople »

A checksum that changes parameters depending on length? That's a new one :lol: good find! Sounds like the kernal routine needs a fix....
Eirik Stople
Posts: 14
Joined: Thu Jun 04, 2020 8:57 pm

Re: KERNAL CRC call (not sure if right)

Post by Eirik Stople »

Sounds like I just got lucky for my bootloader checksum, which indeed is for 512 bytes
Xiphod
Posts: 595
Joined: Thu Apr 15, 2021 8:05 am

Re: KERNAL CRC call (not sure if right)

Post by Xiphod »

Ok, confirmed, the behavior is as expected for a larger example that is >255 bytes.

Here is a BASLOAD example that demonstrates this. It writes an expected static set of data into BANK RAM. I tried doing POINTER(x) of a DIM'd array, but I wasn't yet able to really decipher what the returned pointer in that case is (specifically something like DIM SAMPLE%(1000); I'll just say the returned address in that case seems a bit odd and I couldn't reliably get to the array'd data). So instead, this gave me an excuse to exercise the KERNAL memory_fill function.

Code: Select all

REM ---------------------
REM "VIRTUAL" 16-BIT REGISTERS IN ZEROPAGE
REG.R0.LO=$02
REG.R0.HI=$03

REG.R1.LO=$04
REG.R1.HI=$05

REG.R2.LO=$06
REG.R2.HI=$07

REM ADDRESS OF PASS-THRU PROXY OF ACTUAL ACCUMULATOR REGISTER
REG.A=$030C

REM PERTINENT KERNAL SYSTEM CALLS
KERNAL.CRC = $FEEA
KERNAL.MEMFILL = $FEE4
REM ---------------------

REM STEP 1: PREPARE SOME STATIC DATA TO BE CRC'D
REM FILL 256 BLOCKS, 16 TIMES, STARTING AT $A000

REM USE R0 TO DIRECT WHERE TO FILL
N = $A0
POKE REG.R0.HI, N
POKE REG.R0.LO, $00

REM SET AMOUNT TO FILL (256 BYTES)
POKE REG.R1.HI, $01 : REM 256 BYTES
POKE REG.R1.LO, $00

FOR V = 0 TO 15
  PRINT HEX$(N);"00 ";HEX$(V)

  REM PERFORM THE 256 BYTE FILL
  POKE REG.A, V
  SYS KERNAL.MEMFILL

  REM INCREMENT THE HIGH PORTION OF THE ADDRESS
  N=N+1
  POKE REG.R0.HI, N
NEXT V

REM STEP 2: COMPUTE CRC OF THE STATIC DATA INITILIZED ABOVE

REM SET R0 TO WHERE TO START FROM (WHICH ADDRESS)
POKE REG.R0.HI, $A0
POKE REG.R0.LO, $00

REM SET R1 TO SIZE/LENGTH OF DATA STREAM (4KB == 4096 BYTES
POKE REG.R1.HI, $10
POKE REG.R1.LO, $00

REM INVOKE THE CRC COMPUTATION
SYS $FEEA : REM KERNAL.CRC

REM REPORT THE CRC VALUE
CRC.HI = PEEK(7) : REM REG.R2.HI)
CRC.LO = PEEK(6) : REM REG.R2.LO)
CRC.VALUE = CRC.HI*256+CRC.LO

PRINT HEX$(CRC.VALUE)
This results in $0ED9.

Attached is the intended sample data, represented in a hex sequence. Feed that sample into the reference CRC website, and we get an independent matched result.

The Python and C code earlier also matches this result. The data was prepared with a simple loop like this;

Code: Select all

  for (int y = 0; y < 16; ++y) {
    for (int x = 0; x < 256; ++x) {
      crc16(&crc, y);
    }
  }
Again, this is for "large data" cases (>255 bytes).
crc3.jpg
crc3.jpg (299.01 KiB) Viewed 3686 times
EDIT: I also repeated the above, reducing from 4096 down to 300 bytes - and everything matches (consistent CRC for that case). So yes, as coded in the KERNAL there is this different CRC behavior between the 255/256 byte threshold.


I'm not sure I'd call this a "bug" in the KERNAL - I guess the community can mull it over and decide. Obviously, someone went out there way to make the behavior that way. And it's not a crash-causing issue, so under the "no breaking changes" rules we could just lean towards this being known behavior now.
Attachments
4KHEX_SAMPLE_16_BY_256.TXT
(12.03 KiB) Downloaded 176 times
Last edited by Xiphod on Fri Jan 10, 2025 11:03 am, edited 2 times in total.
Xiphod
Posts: 595
Joined: Thu Apr 15, 2021 8:05 am

Re: KERNAL CRC call (not sure if right)

Post by Xiphod »

Updated the original BASLOAD example in first thread, to show the correction to the issue (by reversing the given BASIC string to be CRC'd)
Post Reply