Jump to content
IGNORED

Playing VGM files in XB (?)


Recommended Posts

OK, so I've hesitated a long time in asking this cause I figure it's probably way over my head.  I have no knowledge of assembly (just a BASIC programmer here) which is why I've started a new thread and not just tacked this onto the main VGM Compressor thread (most of the questions over there seem to at least rely on some baseline knowledge that I am lacking and so a lot of that conversation is currently over my head).  I'll try to break it down simply where I'm at: Inside the VGM Compressor toolkit there is a Players folder with a bunch of player routines including one for XB.  I loaded this XB player from the included vgmcompXB.dsk image.  It works sure enough and I do think I understand how the code works in principle.  My question lies with the music file itself--in this case the file is called GUILE (Guile's theme from Street Fighter 2 I think).  I figured this must be one of those .SBF files that the VGM compressor creates but there is something different about the file.  For one thing, all of the SBF files I've created myself will not play with this player when I try to load them directly (with the folder mounted as a disk in Classic99).  And when I tried to put my SBF files onto that .DSK image with TI DIR I found that they weren't already in TI FILES format and the program was asking me things about how to write the files that I really wasn't sure about (maybe this is part of the problem in that the SBF is not formatted quite the way I need from the get-go).  Also I tried extracting that GUILE file from the disk image into a folder so I could access it with the VGM Compressor tool set but the testPlayer doesn't recognize it.  So clearly there is something different about this file.

 

Looking through the included readme.txt I see that the music must DEFine a label named "MUSIC"--or is it the program itself that has to define a label named "MUSIC"?  Looking through the included BASIC code I can't find any label called "MUSIC" so I assume it has to do with the SBF file?  This is the part I don't understand, probably due to the fact that I don't know assembly...  I'm sure this is why my SBF files don't work out of the box.  Can someone explain to me what I need to do with the SBF files or how to structure them to work with the included XB player?  Or am I indeed in way over my head here?  

 

Thanks!

Link to comment
Share on other sites

I think you're asking multiple questions here.

 

On the subject of TIFILES headers - yeah. If you are moving files from the PC to a TI disk, then you need a header to tell the emulated TI what it is. And if you move it back to the PC, no, the testplayer doesn't know what a TIFILES header it and it won't make sense of the data.

 

To load your music will require you to do some work. Once you have the SBF file, you need to convert it to something that can be loaded by the XB loader, and yes, you need to add the DEF label. The SBF file on the PC side is a binary file.

 

If you look at guile.a99, you'll note the comment:

 

* Data file guile_gb.vgz.sbf - Sep 04, 2021 (DEF and END added by hand)

 

The datafile itself was created by my bin2inc tool, which takes a binary file and creates the assembly source that you see there.

 

https://harmlesslion.com/software/bin2inc/

 

The command line in this case was:

 

bin2inc guile_gb.vgz.sbf guile.a99 MUSIC TI

 

bin2inc - command

guile_gb.vgz.sbf - input file

guile.a99 - output file

MUSIC - label to attach to the data

TI - output TI assembly format

 

I then opened guile.a99 in notepad, and added the "  DEF MUSIC" line to the start, and the "  END" directive to the end so that it could be assembled as a stand-alone module.

 

In this case I probably used WinAsm994A to assemble it into an object file, which I dropped into the Classic99 folder. It should be possible to use xdt99 as well, though I don't have the command line handy.

 

Note in either case while you have TI formatted source code, it's still a Windows PC file. If you use the above tools, the output is also a Windows (or Linux) text file, not a TI file.

 

There's lots of ways to convert files to TI format. For my part I usually just use Classic99... though this trick will only work with source and uncompressed object files (mind you, I believe XB can only load uncompressed anyway?) if you have either of those, you can just load up Editor/Assembler and use the EDIT/PRINT function - source file is your input (ie: DSK1.GUILE.OBJ), and for the printer just specify the output file (ie: DSK1.GUILEO). Classic99 will read the windows file and write the TI version. For other tools consult their creators.

 

Once it's correctly in TI format, it should be loadable in XB. The DEF MUSIC will make the label available to the XB linker as described.

 

All that said, the example guile_gb.vzg.sbf should play fine in the test player. It does for me!

So in short, the intent is to do most of this on the PC side - any tool can be substituted but I list the tools I used:

 

1) create your SBF file

2) Convert to assembly source code (bin2inc)

3) Assemble to TI uncompressed object file (WinAsm99)

4) Convert to TI format (Classic99)

5) Load as per the readme

 

 

Edited by Tursi
  • Like 3
Link to comment
Share on other sites

Thank you both for the quick responses!

 

56 minutes ago, Tursi said:

I could probably write a tool to do the conversion... but I won't be able to for some weeks.

Thank you, you are too good to me!  I appreciate your explanation above--clearly there were a bunch of things I was missing, gaps in my understanding (exactly as I knew there had to be).  But you've laid it out concisely enough that I do follow and may yet manage...  I need to get your tool bin2inc and WinAsm99.  Again, thank you for making it make sense to me!

 

19 minutes ago, ti99iuc said:

@ruthven I can't help with your specific questions more than Tursi has already done.

Anyway when I read about VGM in XB I remembered about this


I don't know if it could help you in some way... but it is worth trying I think.
 

Thank you, yes I do remember stumbling across this a while back but somehow I totally missed that it has the ability to convert to BASIC code.  Converting to CALL SOUND statements is fascinating to me and I wonder if this might work in conjunction with the sound tables that can be setup in XB256...  That would be super cool and I wonder how that method might compare to Tursi's method outlined above.  I will definitely be trying all this out, thanks guys!

  • Like 2
Link to comment
Share on other sites

The biggest difference really will be that my tool compresses the audio, so it will eat less memory, and it will be able to handle faster sound changes than BASIC. But if BASIC/XB CALL SOUNDs work for your project, by all means! I don't know how stable or not my XB player is - I'm not sure if it was ever used.

 

 

Link to comment
Share on other sites

Sorry to be a nuisance but I'm still having some trouble here, though I'm further along.  I've downloaded all the above tools and followed the above outline.  I took a few SBF files and first I put them through the bin2inc tool with the same parameters as outlined above to create an .a99 file.  I then edited that file in Notepad and added the DEF MUSIC at the top and END at the bottom.  Then I assembled this with WinAsm99 (under assembler options I chose Produce HEX Obj File and did not check off the compressed obj box so as to leave it uncompressed (bear with me, this is the first time I ever used this or assembled code so I don't really know what I'm doing).  So this made the .OBJ file and I loaded that in Classic99 under the Editor/Assembler in the way described above with EDIT/PRINT--everything seemed to go smoothly and it produced a file.  I'm not sure how to play the file though...  I opened the example program that plays the GUILE tune and changed the filename to point to my file but this gives me an I/O ERROR 02 when trying to load.  Does this have something to do with the size of the music being different than the original supplied tune or some difference in the addressing?  I was looking around in the BASIC code and I couldn't figure it out--looked to me like the code was setup to auto-detect addressing and stuff...

 

I also did try out that VGM2XB converter but unfortunately I couldn't get it to work with the few VGMs I tried.  I see from the original posting that it was based on an older version of the VGM Compressor toolkit so perhaps it only works with SN76489 type VGMs (I was trying Gameboy and NES).  While I think Tursi's player would be the more efficient route for any reasonably complex music, I do think VGM2XB could be very useful for sfx at least and will delve further at some point.

Link to comment
Share on other sites

Unfortunately the TI error codes are not terribly descriptive. I usually advise people with an IO Error they don't understand to open the debugger and read the debug log. Because Classic99 generates the IO Error code, it can tell you there in much more detail WHY it generated it.

 

Size makes no difference, as long as it fits in RAM. Best troubleshooting step here is to share your file. But if I were to guess, I would guess that you copied the OBJ to the disk image and tried to run it from there. Most likely, you didn't convert it to the correct type in that case. This is something even I struggle with getting right in one try - I hate disk images. ;)

 

Your steps sound right, but share your files and it'll be easier to see where it went wrong.

 

  • Like 1
Link to comment
Share on other sites

Thanks very much for taking the time to help me!  Good to know I at least have the process correct now!  Yeah, I remember you telling me before how you disliked disk images--in fact, you got me to stop that practice a while back (I was running into bizarre issues in some programming projects until I started working with folders/FIADs and the issues ceased).  So yeah, when I copied over the .OBJ file I simply copied it into a subfolder of Classic99 that I had mounted as DSK1.  This folder contained all the raw files including your demo program (I extracted those files from the disk image into the folder).  I "printed" this object file to a TI file per your instructions in the Editor/Assembler cart.  Everything seemingly went well except that none of the files I created in this way loaded in the player.

 

So here are some of the files.  Track 1 is the longer track and track 2 is pretty short--the TI file for track 1 is called MS1 and for track 2 it's TITLEO.

track1.zip track2.zip

  • Like 1
Link to comment
Share on other sites

I was hoping for the disk files too so I could verify all your setup, but that's okay. I will list in detail what I did here.

 

I'm working in a FIAD folder, no disk image.

 

Unzipped your files to a new folder. Copied the sample XB player "tiSNonly.obj" to the same folder and set it in Classic99 as DSK1 with default settings. Just to be able to prove my setup works, I also copied guile.obj from the same folder. Selected Extended BASIC.

 

-- Test setup --

 

Just going to test the player from the command line. Because Classic99 FIADs can read text files, I don't need to convert the OBJ files to do this part. I have the debugger window open to the log so I can spot errors. I have Overdrive on to speed the loading.

 

CALL INIT
CALL LOAD("DSK1.TISNONLY.OBJ")
CALL LOAD("DSK1.GUILE.OBJ")
CALL LINK("SONGGO")

 

This works correctly for me. To make sure there's no nasty interrupt conflicts going on, I cold reset and go back to XB.

 

-- Test your songs --

Now I'm going to repeat the process using the files you provided. Again, I'm going to start by using the OBJ files first, since without disk images I can get away with that. ;)

 

First I open the .OBJ files (CRED.OBJ and title.obj) in notepad to make sure they ARE indeed Windows text, and they are.

 

CALL INIT
CALL LOAD("DSK1.TISNONLY.OBJ")
CALL LOAD("DSK1.CRED.OBJ")
CALL LINK("SONGGO")

 

This plays quite nicely. Let's double check with the other song.

 

CALL INIT
CALL LOAD("DSK1.TISNONLY.OBJ")
CALL LOAD("DSK1.title.obj")
CALL LINK("SONGGO")

 

Sounds pretty good too. So I'm going to guess the problem is in the conversion to TIFILES formatted file. Maybe I lied to you about the print function.

 

CALL INIT
CALL LOAD("DSK1.TISNONLY.OBJ")
CALL LOAD("DSK1.TITLEO")
CALL LINK("SONGGO")

 

Yep, this gives I/O Error 02 on TITLEO. The debug log truncates, I need to fix that, but it is saying "Incorrect file type: 128/DV80 (real) vs 0/DF0 (req...". What this means is that XB asked for a Display, Fixed file (of any record length), but the actual file on disk is Display, Variable 80.

 

And this is entirely my fault. When I recommended the PRINT conversion technique I forgot that uncompressed object files HAVE to be fixed record length, and PRINT always writes variable length. So I must apologize for sending you down the rabbit hole on that one.

 

To make it up to you, here's a little windows tool that will convert the .SBF file directly into a TIFILES formatted DF80 object file, ready for loading. Should save a few steps anyway!

 

tibin2robj.zip

 

To use it, just pass in the input name of your SBF file, and the output filename (tip: can write directly to your Classic99 DSK folder). It's a fully formatted TIFILES file and should also copy directly to disk images if desired without issue (although I have not tested this as I am hours past where I meant to be right now. ;) )

 

For the record, I just added this to my very hacky object file tools here: https://harmlesslion.com/software/tiobj2bin/

 

I should note - in your real program - it is good practice to CALL LINK("STOPSN") after loading TISNONLY.OBJ - this initializes all the data structures to ensure nothing goes sideways when the interrupt is turned on. This is what is done in the sample player program.
 

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

Oh man, again THANK YOU so much!  This tool you've made is awesome and works perfectly for me!   :)

 

21 hours ago, Tursi said:

I was hoping for the disk files too so I could verify all your setup, but that's okay.

Not sure what you mean here by "disk files"--do you mean disk image files?  Because I no longer work inside of them directly when programming stuff in Classic99.  That's given me problems before.  Sorry if I wasn't clear on that.  I only use disk images after I've finished my work and put everything onto CF7 images to transfer to my real TI. :)

 

21 hours ago, Tursi said:

And this is entirely my fault. When I recommended the PRINT conversion technique I forgot that uncompressed object files HAVE to be fixed record length, and PRINT always writes variable length. So I must apologize for sending you down the rabbit hole on that one.

No problem, just glad it wasn't some stupid oversight on my part.  And now with your new tool I guess I won't have to worry about all this in the future.  It seems pretty automated now.

 

Quick question (at least I hope it ends up being quick): once a song has loaded and played through to the end is it possible to load another track?  I did try this of course after the tune had finished by FCTN-4 to break out of the program and modifying the line where it loads music to load another track (at line 150).  I then re-ran the program directly at line 150--it did seem to load the new file but when I went to play it, it just played the first file that I had loaded.  When I tried to load that second music file, did it actually load somewhere in memory after the first track with the player routine still pointing to the first track?  If so I suppose that's probably ideal for having multiple music tracks in a game...  Otherwise I'm wondering if it is possible to clear the music data completely after it plays so that a new track can be loaded in it's place?

 

Sorry for all the questions--appreciate your time!

  • Like 1
Link to comment
Share on other sites

No, by disk images I just meant all the files you are using for your test - including the files I wrote. That helps to eliminate configuration issues and obsolete or corrupt files.

 

The linkage between the player and the song is defined by the XB loader. So when you loaded the second song, all the references to "MUSIC" were already resolved, so the new song didn't get linked into the player.

 

To do multiple song files you need to update that pointer, because I wasn't nice enough to make that easy. ;)

 

The easiest way to do this is compile all the songs that you will need into a single SBF file (just pass multiple files to vgmcomp2 and it will pack them all together.) Of course you need to make sure it stays small enough to load in memory!

 

Once you have that sorted, you'll use the subroutine at 12000 to change the song index 0 is the first song in the pack. If you pass a number that's higher than the number of songs, it will probably crash, so be careful with that.

 

I'm looking at the sample code here, and I see that the CALL LOAD is missing:

 

12090 REM REMOVED CALL LOAD, WE JUST WANT TO READ IT

 

So, you would have to change that to:

 

12090 CALL LOAD(N,I)

 

You'd use it with something like this (to set song '1', which is the second one):

 

10 I=1::GOSUB 12000

 

I haven't tested this since I wrote it, so you'll have to just try it and see if it's right ;)

 

  • Like 1
Link to comment
Share on other sites

Ah I see, thanks for that info.  I had always wondered how to pack multiple songs into a SBF so that's good to know.  Of course this is the proper way of doing it, but it does have me wondering how many tracks I could even pack in given the memory constraints.  I'll have to try it out and see.  But let's just say I had a whole bunch of music I wanted to get in (which I do for a certain project at least :) ) -- is there a way I can clear the music data out of memory and then just load more from another file?  I'm thinking like I'd have a SBF file with 2 or 3 tracks of music and have the game play them, then at some point later it could clear the music data to free up enough room to load another SBF file with more music?  If this is possible, theoretically I could keep doing this to have a bunch of varied in game music.

Link to comment
Share on other sites

Well, right now your songs are about 3k. If you want to stay in the lower memory bank, you can go up to (almost) 8k.

 

It's absolutely possible to free memory and load a new song bank, but it's going to take a few CALL LOADs. 

 

This is going to be necessarily technical, because you have to work around the loader and lie to it to get what you want.

 

The way I would do it assumes you want no other assembly language, or at least that you can load the assembly before the player. Also, if you are going to compile this XB title, then you will need Senior Falcon's help as this won't work there, I don't think.

 

So while researching this, I learned I lied a little bit. The player does NOT rely on the linking loader to find the music. It actually explicitly searches the REF/DEF table for the label named 'MUSIC'. Happily, that makes this a little easier. It starts at the top of memory (so the first loaded thing) and searches down for "MUSIC " or "music "

 

So what's a REF/DEF table? This is just a lookup table of names to memory addresses that the loader creates. It lives at the top of low memory - if you set your Classic99 debugger to CPU memory at >3F00 you can watch names get loaded into it. (Interestingly, looks like I don't check for the end of the table, so if you didn't load something it will search all the way to the bottom of low memory, and if it ever finds that string it thinks that's it. So always save your program before you test it, so it doesn't crash and take your work with it.)

 

I would first load the player itself (CALL LOAD("DSK1.TISNONLY.OBJ"). if you want other assembly language support, load it BEFORE the player.

 

Now what we do, is save a copy of the free memory pointers that the loader uses. This will make it easy to reset the state to this same scenario. There are two pointers in question:

 

>2002 - bottom of low memory -- this is the next free address where CALL LOAD will store loaded data

>2004 - top of low memory -- this is where the bottom of the REF/DEF table starts

 

These pointers are only valid after CALL INIT, and we particularly want them after loading everything that won't be changing. If we save those two pointers, and change them later, we can make the loader 'forget' that we loaded something.

 

Extended BASIC doesn't like hexadecimal, so we have to convert the values to signed integers. That works out to 8194 for bottom and 8196 for top. Since they are side by side, we can fetch all four bytes at once. So, using your own line numbers:

 

1000 REM SAVE THE POINTERS

1010 CALL PEEK(8194,BOT1,BOT2,TOP1,TOP2)

 

You only need to save these pointers once in your program if the music bank is all you ever want to reload.

 

Load and run your music normally. When you want to load a new song, make SURE you call STOPSN first to avoid crashing. Then execute this LOAD to forget the last loaded song bank:

 

2000 REM RESTORE THE POINTERS

2010 CALL LOAD(8194,BOT1,BOT2,TOP1,TOP2)

 

Naturally, if you never did the CALL PEEK, then the zeros will load garbage into memory and your next CALL LOAD("DSK1.xx") will certainly not do what you expect, if it doesn't crash. After that CALL LOAD, the next data file you load should overwrite the previous one.

 

There's only one gotcha here -- because the player just searches all memory, /IT/ won't forget your previously loaded song. But I don't think that's an issue you'd be surprised by.

 

A quick test here suggests this should work fine though.

 

 

 

Edited by Tursi
  • Like 2
Link to comment
Share on other sites

Thanks again for that very thorough response, I appreciate you taking the time to research the answer!  And for laying it out in simple terms.  To be honest I haven't tried this out yet as I'm not nearly there yet in my code--I was just asking ahead of time.  Didn't mean to send you doing any real work on my behalf in researching my answer! :)

But unfortunately I'm having another issue in my current project...

16 hours ago, Tursi said:

if you want other assembly language support, load it BEFORE the player.

Yeah about that, time for the million dollar question: I'm guessing there's just not enough memory to load this player/music inside of a TML project (?)  And I totally get it if the answer is no, seems like a tall ask.  I tried loading my Missing Link project, omitted the CALL INIT and tried just loading TISNONLY and got a MEMORY FULL error.  And with the CALL INIT I then lose the TML commands afterwards, so obviously that won't work.  To complicate things, yes I am compiling this project as it requires the speed given some complicated animations.  So I get that this is a very tall order. :)  That said, I have other TML projects that don't necessarily have to be compiled and if it is possible to get them working with music that would be great!--again, I get that even that may be asking a bit much here.

 

Either way, thank you for all your help in getting me to this point.  Even if I can't use it with TML projects, I certainly do have plans to use it in regular XB games--I've already got it working in a very preliminary kind of way in an old XB game I've had on the back burner for a few years now.  It's a classic style XB game with small 8x8 character graphics and I have to say, it's amazing the level of gravitas that is added simply by adding some nice chip tunes!  All of a sudden it's feeling more like a NES game!

 

But in general I've been gravitating more towards The Missing Link as of late, mostly for it's bitmap loading abilities (which I'm using prolifically in conjunction with your Convert9918 program :) ) and for it's enhanced sprite abilities compared to plain XB.  I do want to try out XB256 sometime as well for access to extra tile patterns but for now I'm loving those bitmaps in TML.

  • Thanks 1
Link to comment
Share on other sites

I am on vacation now, but when I return I will study your problem in more detail. I have been working with SteveB on how to add additional A/L subs to a compiled program, and this method may work for you.

How long is your program? That may be a limiting factor.

Link to comment
Share on other sites

The player isn't terribly big... but there's actually an easy thing to try. You are right - you do not need CALL INIT after you load TML. So the first note I have - load your program into TML, then do that CALL PEEK statement from the command line (ie: no line number). Then PRINT TOP1,TOP2,BOT1,BOT2 - and we'll see how much memory is free in low memory.

 

It /is/ also possible to load all this stuff in high memory. In fact Senior Falcon has some tools that let you do that and also load it with your XB program. But my reload trick won't work in that case - XB only wants to load to low memory IIRC.

 

My player does chain the interrupt hook, so it shouldn't break TML at least. ;)

 

I tried it here, and while I am not sure I have the latest TML (I used TML20, but I named it that so I've no idea). Anyway, I get a bottom of >3EFE, and a top of >3F00. Which means there are 2 bytes free - which isn't enough for anything. ;)

 

Code and data both work in high memory too, which is the program space that SIZE gives you. Noting that whatever Senior Falcon comes up with will be superior, as he knows this system inside out, the hack I would do would to use absolute data. 

 

There's two kinds of loadable data: relative, and absolute.

 

With relative data, which is what you are loading with CALL LOAD right now, the computer figures out what memory is free and stores it there. There's enough information in the file for the computer to fix up all the addresses so that it can actually run.

 

With absolute data, there's none of that. You tell the computer "You WILL load it at this address", and the computer asks no questions, does no fixups, and just puts the data where you told it to. This is simpler, since you don't need to store any fixup data or spend time doing it, or track free memory, or anything. However, it's also more dangerous since the loader doesn't care what might have been there before - it will just scribble right overtop of it.

 

So, the first trick would be to figure out what addresses are free. This means looking at how much memory you use and expect to need to run.

 

The player plus its data storage needs about 1042 bytes. With the size of your program and the knowledge of the program size, you can guesstimate how much memory you have free for your music files. Then you can choose an address to load the player at, and an address to store the music at. As long as all the music files are at the same address, they'll just overwrite each other. We'd need some very small changes to the files to make that work.

 

 

  • Like 1
Link to comment
Share on other sites

I misunderstood the question. Sounds like you are not compiling, but instead are running TML normally from XB. 

As Tursi notes, TML uses all of low memory.

In the XBGDP there is a utility called HMLOADER. This adjusts some pointers so you can put assembly code in high memory. The code is embedded in a one line XB program. Then you can merge in lines of code, or"paste XB".

When you CALL LINK, XB first looks through the def table in high memory. If the al sub is not found, then it looks for the sub in the table in low memory. So this should  let you use the sound player and the TML routines as well. 

No need to use AORG. But be sure to reserve needed buffer space with BSS.

Edited by senior_falcon
Link to comment
Share on other sites

RXB since 2000 has had a subroutine CALL IO that plays music lists the same ones we see used in cartridges and games.

 

Is this new music player able to do more then what CALL IO does?

Link to comment
Share on other sites

2 hours ago, RXB said:

RXB since 2000 has had a subroutine CALL IO that plays music lists the same ones we see used in cartridges and games.

 

Is this new music player able to do more then what CALL IO does?

Significantly. But it's not exactly new, I released the first version in 2014 and the second version, which we are discussing here, in 2020.

 

  • Like 2
Link to comment
Share on other sites

 

Thank you all for chiming in and sorry for the delay in responding (just got my internet back after a storm).  

 

On 3/24/2024 at 8:04 AM, Tursi said:

So the first note I have - load your program into TML, then do that CALL PEEK statement from the command line

So I typed CALL PEEK(8194,BOT1,BOT2,TOP1,TOP2) and then PRINT TOP1,TOP2,BOT1,BOT2

I get: 63     0     62     254     (not sure what all that means :)  It's a fairly large program and that zero maybe doesn't bode well :) )

 

On 3/24/2024 at 8:04 AM, Tursi said:

With the size of your program and the knowledge of the program size, you can guesstimate how much memory you have free for your music files.

That's a bit complicated for me at the moment because my game isn't nearly finished yet. :)  I'm not sure if I gave the impression that my game is complete and just needs music--far from, I'm simply at a point where I really wanted to see what my little "demo" as it is for now felt like with music added to it.  Also I think in any case, this game is going to be much too large to fit inside a single program file.  The game is going to have to be split up into several sections as chain-linked XB programs.  I'm hoping that each individual program in the chain (or section) can load it's own music.  So I will have to leave enough memory free in each to hold at least a track or two.  My idea was to clear the music data in between loading XB programs so that memory could keep being reused and loading new music from files on disk.

 

On 3/24/2024 at 8:04 AM, Tursi said:

It /is/ also possible to load all this stuff in high memory. In fact Senior Falcon has some tools that let you do that and also load it with your XB program.

Sounds like I'm probably going to need to do that.

 

On 3/24/2024 at 8:04 AM, Tursi said:

But my reload trick won't work in that case - XB only wants to load to low memory IIRC.

So if I understand this correctly, if I am forced to go the high memory route (as it sounds to me like I may be) then I will NOT be able to clear the music data that is already in memory and reuse this space for loading more music from file?  Which considering what I'm trying to do here, I might be in a Catch-22 situation.

 

On 3/24/2024 at 8:56 AM, senior_falcon said:

I misunderstood the question. Sounds like you are not compiling, but instead are running TML normally from XB. 

As Tursi notes, TML uses all of low memory.

No you didn't misunderstand...  sorry, I think maybe I wasn't clear--ideally I would like to get all this working in a compiled TML project.  I was just noting how that might be a tall order and I would also be satisfied getting it to work in regular non-compiled TML.  But that would be for another project I am working on--not the current one that had me all excited to even start this post to begin with.  Yes, I am working on far too many concurrent projects! :)  Most are TML.  A couple of these will probably be able to remain regular non-compiled TML once they are finished.  And I also do have a couple regular plain-vanilla XB projects that could benefit from the music as well.  So I was simply trying to state that I was happy to get music going in any of these scenarios.  But within a compiled program would definitely be the gold standard! :)  Now that I've started compiling my stuff and seeing what can be accomplished, it's kind of hard to go back...

Link to comment
Share on other sites

I think this should be possible. (Perhaps that's just the optimist in me coming out.) This is assuming each section of the program has its own music that gets loaded with the XB program when it is loaded. I will need music files from you and instructions on how to use them. I won't be able to do anything till this weekend.

 

It's a bit of a dance - both music and the program must fit in 24k, so you should plan carefully how much to allot to each.

Edited by senior_falcon
  • Like 1
Link to comment
Share on other sites

Thanks very much, I appreciate your willingness to look into this for me!  But now that I know the size limitations I need to work within, I'm afraid my code is going to need some serious optimizations first.  I don't know how big my program file is in TI standards but in Windows it is 23KB.  Plus Tursi's routine itself I think he said takes about 1042 bytes.  So I'm probably over the limit already and this before even loading the music file.  So apparently I need to do a lot of optimization to get my code down in size.  This can probably be done--the main thing that bloats it is a lot of text.  I didn't worry about this at the time because this is only the title/introduction to my game--I figured I'd get all of the introductory text out of the way here and then load the main game engine program.  But it seems I've already painted myself into a corner.  What I will probably have to do is offload the text into a file that can be read as I need it.

 

Sadly this is the case for all of my recent TML projects--they are all over that 24KB mark already even though none of them are complete. :/  Again, they are all text heavy and I wasn't really worrying about it at the time because my plan was always to do the chain-load technique.

 

So I got some work to do before I take up any of your time--I will get back to you though and appreciate it! 

  • Like 1
Link to comment
Share on other sites

Ah, but that's the joy of retro programming - welcome to limitations! Your task - defeat them! :)

 

But yeah, to answer your reply to me just for education's sake:

 

9 hours ago, ruthven said:

So I typed CALL PEEK(8194,BOT1,BOT2,TOP1,TOP2) and then PRINT TOP1,TOP2,BOT1,BOT2

I get: 63     0     62     254     (not sure what all that means :)  It's a fairly large program and that zero maybe doesn't bode well :) )

Because the numbers are all 16-bit, but CALL PEEK only accesses 8 bits at a time, we get 4 numbers for those two pointers. To convert them, we just have to add them together. The first number is the most significant, so it's 8 bits greater in magnitude than the first one... I don't know an easy way to explain why clearly, so I'll just say the total value is FIRST*256+SECOND.

 

So you get BOT is 63*256+0 = 16128 = >3F00 (use a calculator to convert to hexadecimal)

TOP is 62*256+254 = 16126 = >3EFE

 

That means the free memory in the low memory block is from >3EFE to >3F00, or from 16126 to 16128... that is, 2 bytes. And I'm not 100% sure that's safe to use since sometimes pointers are inclusive inside the range and sometimes out. Anyway, yeah, it's full. ;)

 

Quote

So if I understand this correctly, if I am forced to go the high memory route (as it sounds to me like I may be) then I will NOT be able to clear the music data that is already in memory and reuse this space for loading more music from file?  Which considering what I'm trying to do here, I might be in a Catch-22 situation.

 

Absolutely still possible, just not using the exact PEEKs and LOADs that I posted. :) XB doesn't track high memory with CALL LOAD.

 

Not going to share the details, since you have better options coming, but I did a quick test here. Changing the BOTTOM and TOP pointers to point to high memory absolutely allowed XB to load the program and data up there. One more quick CALL LOAD to patch where the player searches for the music (since it needs to search high memory instead) and it did indeed play fine. But at this point, this is as good as absolute data anyway, since you still need to choose the values that you are claiming are free for the loader to use. And if you're using absolute data, then the whole search part can just be removed since it's only purpose is to figure out where the music was loaded, and you already know that (in that case). ;)

 

Rich's comment also had me thinking. Since you're pretty tight on memory, you might want to store the music in VDP RAM. (Mind you, VDP is pretty tight under TML too, due to the bitmapped graphics!) But if your music CAN be played with the console player, then you don't need the just over 1k of my player loaded in CPU memory, just a small loader that can load the music. We could do it with a PROGRAM file loader since it doesn't need to leave VDP RAM in that case, and it will also load very quickly as a result. You can determine how much VRAM is free with SIZE too, it's the 'stack'... but that will be reduced as your program runs and initializes variables. We'd have to tell XB (and TML?) to reserve memory for the music in that case. But it wouldn't take more than a couple hundred bytes of extra assembly in CPU memory. The player in ROM is fairly basic, but if your song isn't too complicated then even if the files are slightly bigger it might be worth it. (If you want to check, there is a sound list exporter in the VGMComp2 toolchain (psg2soundlist) - use it the same way as vgmcomp2.exe. The result is a binary file that I don't currently have a way for you to easily play, but you can use it to see how big your music ends up being in that format.

 

 

  • Like 1
Link to comment
Share on other sites

You are almost there. With JUWEL in drive 1, type:

OLD DSK1 HMLOADER then RUN

Load your files, something like:

DSK3.TURSIPLAYER.OBJ

DSK3.MUSIC.OBJ

When done enter a blank line.

CONTINUE LOOKUP IN LOW MEMORY? 

Enter Y

The files are loaded into high memory starting somewhere around >A000 to find out how big they are. When that is known they are loaded again, this time embedded in a 1 line xb program. If you use XB2.9 the loading process goes a lot faster. The xb program pokes an address to >2000. This tells CALL LINK where to find the lookup routine. I think that address is always the same. All you need is the tweak to TURSIPLAYER so it knows that new location. 

If a match isn't found after looking through the DEF table in high memory, then the normal CALL LINK lookup is done, so it will be able to find the TML routines.

Add xb program lines to the embedded program created by HMLOADER.

 

  • Like 1
Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...