[Closed?] Endianess weirdness when exporting to source

What is Arkos Tracker? Forums Arkos Tracker forum Bug reports [Closed?] Endianess weirdness when exporting to source

Viewing 15 posts - 1 through 15 (of 19 total)
  • Author
    Posts
  • #831
    ggn
    Participant

    Hi,

    While testing the ST replay source I came across a weird export bug: It seems that when I untick “little endian” (so I want the data in a big endian format), the order of hardware and software periods are reversed.

    Since the player reads those values one byte at a time, I ended up writing the high byte to the low ym byte and the low byte to high ym byte.

    Now, one might ask why don’t I read both bytes in one read – job done? Well, for starters the period bytes are on an odd address, so trying to read a word in one go will result in an exception! And even if that matter was solved then I can’t think of a really fast way to take advantage of this – the register will have to be shifted in order to be written in the ym and shifts aren’t the fastest bit of the 68000. Another idea would be to interleave the register select bytes with the data, so if you want to write $20 to register 0 and $30 to register 1 we could construct a longword like $00200130 and then write that to the psg in one go. However that too will waste a lot of cycles.

    So my suggestion would be to not swap endianess of software and hardware when exporting to source format.

    All this on v2.0.0a2, Windows

    #832
    Targhan
    Keymaster

    Hmmm, I don’t understand how it is possible that the soft/hard 16 bits values can be inverted because of the endianness, but I’ll check anyway. In the meantime, if you have test files that are ready, you can send them to me (contact at julien-nevo dot com) and I’ll have a look. Thanks!

    #835
    ggn
    Participant

    Hi,

    Just mailed you 2 files!

    #836
    Targhan
    Keymaster

    Well, unless I’m wrong, the result looks normal to me:

    big endian: (label Main_Subsong0_RegisterBlock_1421):
    —————————————————–
    dc.b 1, 146 ; Software period.
    dc.b 0, 50 ; Hardware period.

    little endian:
    —————————————————–
    dc.b 146, 1 ; Software period.
    dc.b 50, 0 ; Hardware period.

    Isn’t how words are supposed to be encoded? If I had used dc.w/dw, it would have been encoded the same way. What you are asking is counter-intuitive, and what may suit you needs for the ST player may not be for another hardware, or another player. Did I understand correctly what you wanted to do?

    #837
    Targhan
    Keymaster

    For example, on CPC, we can read 16 bits by using the stack and POPing a word. If another hardware with big-endianness can do that, this trick will be forbidden. I only see problems arising from this!

    (so this is not a bug… and there is nothing weird, only logical :))

    #838
    Targhan
    Keymaster

    Well, maybe I can add an export flag to “force little-endianness when encoding periods”. But then, what about things like:

    dc.b 8 : dc.w Main_Subsong0_RegisterBlock_160 + 6 ; Optimization: goto common Block at index 4.

    Should the dc.w be encoded in little-endian too? Isn’t the problematic the same?

    #839
    Targhan
    Keymaster

    Wouldn’t it be better for your player that you use a 68000 Source Profile but use little-endianness when exporting? This is easy to do: in AT2, create your own 68000 profile, or use the command line tool, using the 68000 profile but overridding the endianness parameter.

    #840
    ggn
    Participant

    Well, the question real question was: why are you exporting this as a word? In the player you are reading the two bytes one by one. When I did that I got the bytes in the inverse order so everything sounded garbled! Also, you seem to export 2 db statements, not 1 dw, so it all falls down there.

    If I exported as little endian, wouldn’t it confuse people more? Export little endian for a big endian machine?

    So what I’m asking is that since you write 2 distinct bytes just write them in the order they will be read, that’s all 🙂

    Also I can’t read the two bytes as a word – if they happen to be at an odd address then the 68000 will trigger an exception error. (this is fixed on 68020 onwards but not in plain 68000).

    #841
    Targhan
    Keymaster

    >Well, the question real question was: why are you exporting this as a word?

    Because that was the logical thing to do, and on CPC, thanks to the little-endianness, it doesn’t matter if you use DB XX, YY or DW YYXX.

    I *thought* 16 bits machine would read 16 bits easier. This is also how I stated this in the documentation of the AKY format:
    dw softwarePeriod
    dw hardwarePeriod

    “dw” being dependent on the hardware endianness.

    >If I exported as little endian, wouldn’t it confuse people more? Export little endian for a big endian machine?

    What is important is what YOUR player needs, which is why the export allows you, via the export options or the Source Profile options, to encode the thing the way you need it. For example, I am working on a MOD player on CPC, requiring the RAW format with precise parameters. As long as it is documented, it is no problem.

    But really, I do understand you point and I am ready to do something about it. But please answer the other questions I asked, notably about the other word encoding: why “db 8 : dw myLabel” does not bother you?

    #845
    ggn
    Participant

    Apologies, I missed that “db 8 : dw myLabel” bit!

    There are 2 possible ways the data will be laid out:
    1) db 8 ending up on an odd address. This means that dw mylabel will end up on even address – no problem, I can read that word directly.
    2) db.8 ending up on an even address. So in theory the dw will have to be odd addressed. But here the assembler kicks in and auto-evens the address before it writes the dw. So the dw will also fall on an even address! Of course this creates a one byte gap between the db and db. For now I have a check on the code that auto-evens the address pointer on PLY_AKYst_RRB_NIS_ManageLoop. I’m not really sure if this can be avoided in the current state of the exported data, maybe if all codes after PLY_AKYst_RRB_NonInitialState are exported as dw.

    But for now this is not a major problem for the ST player – the more pressing matter is to remove all the closely coupled z80 behaviour and replace it with something more friendly for 68000 🙂

    #846
    Targhan
    Keymaster

    Then, what about simply forcing the encoding to little-endian? Would it resolve all the problems?

    #851
    ggn
    Participant

    That’s what I do right now, export source as little endian. I haven’t tried binary export yet but I fear it will not work if the exporter does not auto-even dw exports. I’ll check and let you know…

    #852
    Targhan
    Keymaster

    The exporter will not auto-even DW, because I never expected to have to do such thing! Do you need binary export if the source export works fine?

    One question, what do you do whenever a DW is found? Do a manual pass and add a macro to check the “even-ness” of the address and add a dc.b 0 if odd?
    If yes, what about, in the source profile, instead of declaring “dc.w” for the word declaration, declare a macro call (Example: MY_MACRO_DW MyLabelToCall, and it would generate: dc.b 0 : dw 0, or simply dw 0 if needed). The macro would have to be included manually for now though (but you would probably include it to your “main code”).

    #853
    Targhan
    Keymaster

    Correction from above:
    “MY_MACRO_DW MyLabelToCall, and it would generate: dc.b 0 : dw MyLabelToCall, or simply dw MyLabelToCall if needed)”

    #855
    ggn
    Participant

    Source export is more than adequate for me really. As I discussed with Xia this evening having the tune in source format is very handy if you want to modify it on the fly (for example, changing the loop points).

    As for the auto-eveness, it only happens in 2 places:

    1) In the track definitions:
    dc.b 10 ;Duration.
    dc.w Main_Subsong0_RegisterBlock_3-Main_Subsong0
    In this case I know it’s always one byte followed by a word, and of course a padded zero between. There my code simply skips one byte after reading the duration and then reads the word. So this is an easy case.

    2) When there is a branch command in the register blocks. This one is much more complicated problem because I don’t think I can predict when the loop offset is at odd or even address. For now the player simply performs a manual auto-even of the address – not that efficient but it doesn’t hurt performance much. (https://github.com/ggnkua/Arkos-Tracker-2-ST/blob/master/PlayerAky.s#L1155)

    I suppose I could fix this by parsing the register blocks and see when a “8” command is encountered to check if the address is odd or even. if it’s odd I could move the register block bytes one byte forwards so that the “8” command be immediately before the offset. i.e.:

    abcdef0gh

    if byte “f” is the 8 and “gh” the jump offset then copy abcdef one byte to the right. Of course this will mean I will have to also patch all the places the register block is referenced to point to +1 byte forward.

    This will add a bit of complexity but it’s only at startup so no real harm done. And it means less work for you 🙂

    As for your macro idea, I didn’t get it fully, sorry. Perhaps I’m too tired right now!

Viewing 15 posts - 1 through 15 (of 19 total)
  • You must be logged in to reply to this topic.