artrag Posted November 29, 2018 Share Posted November 29, 2018 (edited) In short: I have binary data generated by a windows editor that can be played by a z80 machine. The binary file packs 16 bit data and 8 bit data in the same stream. It is in accessed by the z80 player almost sequentially, sometimes byte by byte, sometimes word by word. I'm trying to convert the z80 code to intybasic using peek() but it is quite complex and ineffective because I have to keep in mind when the data that the player needs are word aligned, and when no. If the data are not word aligned I need two peeks in adjacent addresses to be merged in one 16 bit result... I've was thinking that building a function able to count bytes in the data stream and return a byte or a world could be a possible solution, even if not very efficient, at least to get something working. But I've the feeling I'm reinventing the wheel and that maybe something ready and efficient is already somewhere... Any idea on how to do something like this ? For those curious of what I'm doing this is the WIP. ayFX_INIT: procedure ' --- INIT A NEW ayFX STREAM --- ' --- INPUT: A -> sound to be played --- ' --- C -> sound priority --- ' --- Checks the priorities of playing ayFX streams to place --- ' --- the new one on the channel with lowest priority --- ' --- Check if the index is in the bank --- b = a ' b:=a (new ayFX stream index) if (peek(#ayFX_BANK) and 255 = 0) then ' Number of samples in the bank goto CHECK_PRI ' If zero (means 256 samples) goto @@CHECK_PRI elseif (peek(#ayFX_BANK) and 255 < b) then ' The bank has less than 256 samples a = 2 ' If new index is not in the bank... return ' a:=2 (error 2: Sample not in the bank) end ' ...we can't init it CHECK_PRI: ' --- Places the data on the correct channel --- ' --- Remember: 0 = highest priority, 15 = lowest priority --- if (ayFX_C1 = 255) then ' If there's no Stream being played... goto TOC1 ' ...place the new Stream on channel 1 end if (ayFX_C2 = 255) then ' If there's no Stream being played... goto TOC2 ' ...place the new Stream on channel 2 end if (ayFX_C3 = 255) then ' If there's no Stream being played... goto TOC3 ' ...place the new Stream on channel 3 end if (ayFX_C2 >= ayFX_C1) and (ayFX_C3 >= ayFX_C1) then if (c<ayFX_C1) then a = 1 ' a:=1 (error 1: A sample with higher priority is being played) return ' ...we can't play the new ayFX Stream end goto TOC1 end if (ayFX_C1 >= ayFX_C2) and (ayFX_C3 >= ayFX_C2) then if (c<ayFX_C2) then a = 1 ' a:=1 (error 1: A sample with higher priority is being played) return ' ...we can't play the new ayFX Stream end goto TOC2 end if (ayFX_C2 >= ayFX_C3) and (ayFX_C1 >= ayFX_C3) then if (c<ayFX_C3) then a = 1 ' a:=1 (error 1: A sample with higher priority is being played) return ' ...we can't play the new ayFX Stream end goto TOC3 end TOC3: ' --- Stream will be played on channel 3 #IX = varptr ayFX_C3 ' Pointer to the chanel data goto SETDATA ' Go to @@SETDATA TOC2: ' --- Stream will be played on channel 2 #IX = varptr ayFX_C2 ' Pointer to the channel data goto SETDATA ' Go to @@SETDATA TOC1: ' --- Stream will be played on channel 1 #IX = varptr ayFX_C1 ' Pointer to the chanel data SETDATA: ' --- Set data on the correct channel --- poke #IX, c and 15 ' new ayFX stream priority saved in RAM ' --- Calculate the pointer to the new ayFX stream --- ld de,[ayFX_BANK] ' de:=Current ayFX bank inc de ' de points to the increments table of the bank ld l,b ' l:=b (new ayFX stream index) ld h,0 ' hl:=b (new ayFX stream index) add hl,hl ' hl:=hl*2 add hl,de ' hl:=hl+de (hl points to the correct increment) ld e,[hl] ' e:=lower byte of the increment inc hl ' hl points to the higher byte of the correct increment ld d,[hl] ' de:=increment add hl,de ' hl:=hl+de (hl points to the new ayFX stream) ld [IX+1],l ' Pointer lower byte saved in RAM ld [IX+2],h ' Pointer higher byte saved in RAM xor a ' a:=0 (no errors) end Edited November 29, 2018 by artrag Quote Link to comment Share on other sites More sharing options...
intvnut Posted November 29, 2018 Share Posted November 29, 2018 (edited) I'll be honest: I'd probably try to do this in assembly language, because I can think of some clever ways to keep the instruction count down. IntyBASIC makes it harder. One approach is to structure it as a "prefetch" so that the only variable paths are associated with refilling the prefetch buffer: . UNSIGNED #prefetch, #index, #datum, packed_data #prefetch = 0 #index = 0 #datum = 0 NextByte: Procedure #datum = #prefetch AND 255 #index = #index + 1 if #index AND 1 then #prefetch = packed_data(#index / 2) else #prefetch = (#prefetch / 256) + (packed_data(#index / 2) * 256) end if end NextWord: Procedure #datum = #prefetch #index = #index + 2 if #index AND 1 then #prefetch = (packed_data(#index / 2) / 256) + (packed_data(#index / 2 + 1) * 256) else #prefetch = packed_data(#index / 2) end if end packed_data: DATA 1, 2, 3, 4, 5 . Another approach that would work well in assembly language, if you have some 8-bit RAM to spare, would be to unpack 16-bit words to 8-bit RAM in chunks (say, 8 bytes at a time), and then use MVI@ or SDBD; MVI@ as needed to read 8 and 16-bit values, unpacking the next few words whenever needed. I can see a way to make that reasonably efficient in assembly, but not so much in IntyBASIC. Edited November 29, 2018 by intvnut Quote Link to comment Share on other sites More sharing options...
artrag Posted November 29, 2018 Author Share Posted November 29, 2018 Thanks for the code, I will start from your solution, in the attempt to get a quick and dirty, but working, conversion. Another idea I was evaluating is that due to the fact that intybasic is not capable of importing binary files, there is the possibility to do an offline converter in C able to interpret the bin file, unpack bytes in words when needed and generate a bas file... I'll let you know Quote Link to comment Share on other sites More sharing options...
artrag Posted December 4, 2018 Author Share Posted December 4, 2018 use all buttons to hear how it is going audio.rom 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.