KERNAL CRC call (not sure if right)
-
- Posts: 14
- Joined: Thu Jun 04, 2020 8:57 pm
Re: KERNAL CRC call (not sure if right)
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.
Re: KERNAL CRC call (not sure if right)
Actually this is right, for that particular system yes I think we had used an external programmer.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.
Re: KERNAL CRC call (not sure if right)
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).
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
Re: KERNAL CRC call (not sure if right)
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.
Eirik has been able to use the Kernal function successfully in the SMC tools he made.
It needs some further checking.
Re: KERNAL CRC call (not sure if right)
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.
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.
Re: KERNAL CRC call (not sure if right)
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.
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.
-
- Posts: 14
- Joined: Thu Jun 04, 2020 8:57 pm
Re: KERNAL CRC call (not sure if right)
A checksum that changes parameters depending on length? That's a new one
good find! Sounds like the kernal routine needs a fix....

-
- Posts: 14
- Joined: Thu Jun 04, 2020 8:57 pm
Re: KERNAL CRC call (not sure if right)
Sounds like I just got lucky for my bootloader checksum, which indeed is for 512 bytes
Re: KERNAL CRC call (not sure if right)
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.
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;
Again, this is for "large data" cases (>255 bytes).
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.
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)
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);
}
}
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.
Re: KERNAL CRC call (not sure if right)
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)