Shop OBEX P1 Docs P2 Docs Learn Events
A strange behavior of the code - what is wrong? [solved] — Parallax Forums

A strange behavior of the code - what is wrong? [solved]

pik33pik33 Posts: 2,366
edited 2022-04-16 18:55 in BASIC (for Propeller)

I am trying to get .sid file header.

This code works wrong:

dim speed, r as ulong
dim version, offset, load, startsong, flags, init, play, songs, song  as ushort
dim il,b as ubyte
dim ititle,iauthor,icopyright as ubyte(32)
dim atitle,author,copyright as string
dim i as integer

mount "/sd", _vfs_open_sdcard()
chdir "/sd/sid/selected"
let filename3$="/sd/sid/selected/bilinski.sid"

close #8: open filename3$ for input as #8

atitle=""'"                                "
author=""'"                                "
copyright=""'"                                "

get #8,5,version,2,r :    version=((version and 255) shl 8) or (version shr 8) : print version 
get #8,7,offset,2,r  :    offset=(offset shl 8) or (offset shr 8) 
get #8,9,load,2,r    :    load=(load shl 8) or (load shr 8)
get #8,11,init,2,r   :    init=(init shl 8) or (init shr 8) 
get #8,13,play,2,r   :    play=(play shl 8) or (play shr 8) 
get #8,15,songs,2,r  :    songs=(songs shl 8) or (songs shr 8)
get #8,17,startsong,2,r : startsong=(startsong shl 8) or (startsong shr 8) 
get #8,19,speed,4,r     
speed=speed shr 24+((speed shr 8) and $0000FF00) + ((speed shl 8) and $00FF0000) + (speed shl 24) 
get #8,23,ititle(0),32,r      
get #8,55,iauthor(0),32,r      
get #8,87,icopyright(0),32,r    

if version>1 then 
  get #8,119,flags,2,r : flags=(flags shl 8) or (flags shr 8)
  b=0 : if load=0 then b=1 : get #8,125,load,2,r  
endif

for i=0 to 31 : atitle=atitle+chr$(ititle(i)): next i  
for i=0 to 31 : author=author+chr$(iauthor(i)) : next i 
for i=0 to 31 : copyright=copyright+chr$(iauthor(i)) : next i  

print ("version:   "): print(hex$(version,4))
print ("offset:    "): print(hex$(offset,4))
print ("load:      "): print(hex$(load,4))  '178-144*b);
print ("init:      "): print(hex$(init,4))
print ("play:      "): print(hex$(play,4))
print ("songs:     "): print(hex$(songs))
print ("startsong: "): print(hex$(startsong))
print ("speed:     "): print(hex$(speed,8))
print ("title:     "): print(atitle)
print ("author:    "): print(author)
print ("copyright: "): print(copyright)
print ("flags:     "): print(hex$(flags,4))

The result:

2
version:   
736E
offset:    
696B
load:      
1000
init:      
0000
play:      
1003
songs:     
1
startsong: 
F24C
speed:     
00000001
title:     
Bilinski
author:    
Wojciech Radziejewski (Shogoon)
copyright: 
Wojciech Radziejewski (Shogoon)
flags:     
0024

"2" written first is the proper version number. However somewhere later it got garbled, and $736e is garbage, The offset, $696b is aiso garbage, while the rest of fields are correct.

However, this code works as expected:

dim version, offset, load, startsong, flags, init, play, songs, song  as ushort
dim il,b as ubyte
dim ititle,iauthor,icopyright as ubyte(32)
dim atitle,author,copyright as string
dim i as integer
dim speed, r as ulong

(... the rest is exactly the same)

The only change is the declaration of speed and r moved from the first line of the code to the last line of the declaration block

The result is now correct:

2
version:   
0002
offset:    
007C
load:      
1000
init:      
0000
play:      
1003
songs:     
1
startsong: 
F24C
speed:     
00000001
title:     
Bilinski
author:    
Wojciech Radziejewski (Shogoon)
copyright: 
Wojciech Radziejewski (Shogoon)
flags:     
0024

What can be wrong here?

The compiler version and parameters:

"/home/pik33/Programy/flexprop/bin/flexspin" -2 -l --tabs=8 -D_BAUD=230400 -O1    --charset=utf8 -I "/home/pik33/Programy/flexprop/include"  "/home/pik33/Programowanie/P2-retromachine/Propeller/Tracker player psram 2/sidtest.bas" -DFF_USE_LFN
Propeller Spin/PASM Compiler 'FlexSpin' (c) 2011-2022 Total Spectrum Software Inc.
Version 5.9.10-beta-v5.9.9-93-ge37a63f5 Compiled on: Apr  3 2022

Comments

  • Wuerfel_21Wuerfel_21 Posts: 5,053
    edited 2022-04-16 15:03

    Try diff-ing the generated assembly between the two cases. That will lead to more insight.

    Also, there have been a few bug fixes since your version, so try re-building I guess

  • pik33pik33 Posts: 2,366
    edited 2022-04-16 15:50

    Too many differences between the .lst files. Then, I started to comment out instructions to find what causes the "version" variable to change.

    get #8,19,speed,4,r

    Commenting it out makes "version" to be unchanged.

    I will try to recompile the the new compiler and try if it is different there. As a workaround in the player, where this error is also present (and from where I extracted the test code) I will simply get the entire header and extract fields out of it.


    Edit: recompiled, nothing changed.

  • I thought file handles had to be between 0 and 7 in FlexBASIC. Is the “8” freaking it out?

  • pik33pik33 Posts: 2,366

    I tested #7, it works exactly the same way. Also I tried to declare several dummy variables between used ones. The result changes depending on how many variables I add, but is still incorrect.

    The player gets a lot of data from files, file handles up to #9 works OK, all file transfers worked as expected before.

  • pik33pik33 Posts: 2,366
    edited 2022-04-16 16:45

    This is the simplest version of bad working code.

    dim speed as ulong
    dim version  as ushort
    
    mount "/sd", _vfs_open_sdcard()
    chdir "/sd/sid/selected"
    let filename3$="/sd/sid/selected/bilinski.sid"
    close #7: open filename3$ for input as #7   
    
    get #7,5,version,2 
    print version 
    get #7,19,speed,4   
    print version
    

    The result:

    512
    26946
    

    512 is what it should be.
    Changing declaration order makes the program work.

  • Hmm, did a quick check, it's not a codegen issue AFAICT. This is the entire difference, as it should be:

    So I guess something goes wrong in __system___basic_get? IRDK...

  • pik33pik33 Posts: 2,366
    edited 2022-04-16 18:39

    Yes, I already compared listings of this simple code. It was simple enough to check - there seems to be nothing wrong in the main program compiled code. It seems as it is __system__basic_get which does something wrong
    If "speed" is declared after "version", all is OK. If it is declared before, "version" is overwritten as if "get" gets more than 4 bytes and overwrites next variables with what it gets.
    In the long "full" version of sid reader, these "bad" values in "version" (and "offset") are not random. They are read from the file at one of these strings location. I will check what exact file position they are from.

    Edit:

    In the simple program from post #6, "version" is declared after "speed" and get before "speed", "version" is overwritten with these 2 bytes which are in the file directly after the "speed"

  • pik33pik33 Posts: 2,366

    Solved.

    The amount field in "get" is not a byte count to load. It is amount of bytes*sizeof(variable) to which it loads.

    When I tell it to get #7, speed, 4 it got 4*sizeof(ulong) which is 16 bytes, overwriting the variables which was declared after.

  • Wow, as a passive observer, this stumped me too:

    GET as described in /doc/basic.md:

    get #handle, pos, var [,items [,r]]

    get is used to read binary data from the open file whose handle is handle, starting at position pos in the file (where pos is 1-based).

    • The position is optional, but if omitted a comma must still be placed to indicate that it is missing.
    • var is the first variable into which to read the binary data,
    • and items is the number of variables to read starting at var.
    • items is often omitted, in which case just one variable is read.
    • r is an optional return value with, if present, is a variable which is set to the number of items actually read.

    Several important caveats apply:
    (1) The bytes are read as binary data, not ASCII.
    (2) Strings may not be read in this way. The compiler will not throw an error for using a string type, but what is read is the 4 byte pointer for the string, not the string data itself.
    (3) The return value r is "items read" rather than "bytes read" as it is in FreeBasic.
    (4) If an error occurs, r is set to -1.

  • pik33pik33 Posts: 2,366
    edited 2022-04-16 19:58

    I have a Pascal background: "get" is equivalent of Pascal's fileread (handle, variable, amount). Pascal's amount is bytes, so fileread handle,variable,sizeof(variable)) and that's why I didn't see the error so long.

    What helped to find the error in the code was the last test I did: I declared a lot of variables, "get" the first of it, printed all of them. It gets 16 bytes... Voila - then I opened the manual and read the text you put above.

    This position numbered from 1 instead of 0 is the second quirk of Basic's get command, but forgetting about this gives an instant error.

    There is a lot to relearn and remember, but from these 3 languages available for P2 in Flexprop compiler, Basic is the easiest to use for a Pascal programmer with (Atari) Basic background from 35 years ago. Maybe I will have to do something also in C, there are still things I cannot do in Basic and the file system. For example, delete the file.

  • evanhevanh Posts: 15,916

    It's a classic, never-ending hazard in C. BASIC normally protects you from it though.

Sign In or Register to comment.