I will not go through the process of sending files to your calculator or using a shell. Check your calculator manual and the documentation that comes with the assembly shell you are using. There are 2 calculator binaries in the ZIP archive - you need to select the appropriate one for you! Each one is exactly the same in functionality.
A music player is useless without music to play! If you look in the /songs subfolder you will see some .8XP files - these are the song files. Please note that the player will not run if you have no song files on your calculator. It will quit automatically without an error message.
You have a music player, but where does the sound come from? The link port! However, you'll notice that the socket is too small for regular headphones. You'll need some sort of adapter, or can use the AM radio trick.
For the sound to be reproduced on an AM radio, tune it to a quiet area in the
MW range. Now, holding the top of the calculator screen near the radio should
produce very low quality sound.
For better sound, you need a converter. All this needs to be is a simple 2.5mm
to 3.5mm stereo jack converter - available (so I hear) from Radio Shack in the
US. I ordered mine through Maplin Electronics in the UK. Plug the 2.5mm hack
into your link port, and then a pair of conventional headphones into the adapted
port. Note that the calculator will seem to 'freeze' with the headphones
inserted - only insert them once you are in an assembly shell, or the sound
program itself.
I had lost my converter by the time I came to write this, so ended up using a
bulldog clip, an old TI to TI connection cable and the extension lead from my
Sony earphones to test the output from the calculator (VTI's sound is a bit
crummy). Plugged into the AUX channel of my HiFi the sound quality was
excellent.
Select and run the program from the assembly shell you are using. You will be presented with a list of songs on your calculator (it displays the track title, not the calculator filename). At the bottom of the screen is a row of commands. You run a command by pressing the blue F key underneath it (the keys F1 to F5 are also marked Y=, Window, Zoom, Trace and Graph). If the command button is shaded out that means that that command button can not currently be used (for example, you cannot fast forward through a song if you haven't got one playing!)
You can go up and down through the list of songs by pressing the up and down keys on your calculator. If there are more songs on the calculator than your screen can display then the list of files will scroll as you go further down.
The different functions are:
You've seen mono sound. Then CalcMod did the unthinkable - adding a second channel by exploiting the fact that the TI had two data lines. Now, I've split those two channels up into two channels themselves, and we now have rich four-channel sound at our disposal - just perfect for decent sounding chiptunes!
You can set the status of the link port directly by outputting bytes to it. The two least significant bits end up as the logic levels of the two data lines. The way that mono sound could be produced was quite simple:
Set the output low.
Fixed delay.
Set the output high.
Fixed delay.
Loop.
By making the delays shorter, the status of the link port would change more frequently over a fixed unit of time - the frequency goes up. The opposite is true if you make the delays longer. You can give the beep a duration in this manner:
Set the output low.
Delay, and each "tick" of the delay decrease the duration by 1. If it's zero,
jump out of the tone loop.
Set the output high.
Delay, and each "tick" of the delay decrease the duration by 1. If it's zero,
jump out of the tone loop.
Loop.
The delays could be structured using the B register and a DJNZ loop, for example.
This is all very well and good for mono sound - how about stereo sound? The "Stereo" aspect is only a side-effect of the process of splitting a monophonic sound into a polyphonic sound. In fact, it's not truly polyphonic at all - you're actually just playing two mono tracks independently. Well, imagine we changed our system to this:
Decrease the value for L. If it's zero, toggle the left
channel and reset L to the original value.
Decrease the value for R. If it's zero, toggle the right channel and reset R to
the original value.
Decrease the duration, if it's not zero, loop.
That's all there is to it. The trick here is that we're no longer setting things high or low - we're just toggling them when the time comes.
The jump to four channel sound is a bit different and is achieved by "interlacing" the sound. Imagine now that instead of a single L/R channel (like in CalcMod), we have two of them. Now, instead of just outputting one of them all the time we switch between them each loop. This is why the sound isn't always as "clean" as it is in CalcMod (sometimes there's a faint extra tone in the background) as you build up harmonics. The software switches channels at a much greater frequency than the higher notes in songs (which is why you should try and stick to the lower end of the scale - also, it's a logarithmic scale so the lower frequency notes are more exact) and thus the sound is still decent.
Sadly, the way that sound on the calculator works is that it takes up 100% CPU time (well, I can get away by using some low-level direct key input, but you can't do much else as it messes up the timing) and thus sound in games isn't yet properly possible. You can output brief beeps in non CPU-intensive games, and the delay is not noticed if the game "does something" at that point (see IceClimb, for example). If you have a calculator that can switch into a higher clock frequency mode you could do some crafty things inside the delay loops, but it's still not something I've seen (and I can't implement as I only have a 6MHz TI-83 Plus).
It's in the /src folder. The files are:
In the /songs folder you'll find some more source code:
This'll need some explaining! Make sure you have an assembler that supports macros (TASM coupled with DevPac8X is perfect).
I've tried to make things easier for you with the notes.inc file. However, the structure of the song files needs some explaining. Firstly, you need the song header:
.org $0000
#include "notes.inc"
title: .db "Bellon - Stage 7",0
artist: .db "Mars Jenkar",0
album: .db "Zero Wing",0
Make sure that you get those sections in - they must be in that order. If you don't want to specify an artist or album, put a space or "Unknown" in. Do NOT erase the line! Also, ensure that you leave the zero at the end of each. Some pitfalls:
Now you have the song header in place, you need to break down your song you wish to write into sections. A simple song might be a section all on its own, but if you think of most songs they repeat bits (such as the chorus or verses) and it makes sense to not have to repeat the code for them.
The way that you define sections is with a label (a piece of text followed by a colon). For example, here is the intro part to the "BELLON" file:
intro:
note(a0,a1, e3,c3, sixteenth)
note(a0,a1, rest,rest, sixteenth)
note(a0,a1, d3,a2, sixteenth)
note(a0,a1, rest,rest, sixteenth)
note(a0,a1, a2,c3, sixteenth)
note(a0,a1, a2,d3, sixteenth)
note(a0,a1, a2,c3, sixteenth)
note(a0,a1, a2,d3, sixteenth)
note(g0,g1, a2,c3, sixteenth)
note(g0,g1, rest,rest, sixteenth)
note(g0,g1, g2,b2, sixteenth)
note(g0,g1, rest, rest, sixteenth)
note(g0,g1, g2,d2, sixteenth)
note(a0,a1, rest,rest, sixteenth)
note(a0,a1, a2,e2, sixteenth)
note(g0,g1, rest,rest, sixteenth)
; just bass
note(a1,a2, rest,rest, sixteenth)
note(a1,a2, rest,rest, sixteenth)
note(a1,a2, rest,rest, sixteenth)
note(a1,a2, rest,rest, sixteenth)
note(a1,a2, rest,rest, sixteenth)
note(a1,a2, rest,rest, sixteenth)
note(a1,a2, rest,rest, sixteenth)
note(a1,a2, rest,rest, sixteenth)
note(a1,a2, rest,rest, sixteenth)
note(a1,a2, rest,rest, sixteenth)
note(a1,a2, rest,rest, sixteenth)
note(a1,a2, rest,rest, sixteenth)
note(g1,g2, rest,rest, sixteenth)
note(a1,a2, rest,rest, sixteenth)
note(g1,g2, rest,rest, sixteenth)
note(g1,g2, rest,rest, sixteenth)
endsection
(If you put a semicolon, ";", anything after it on that line is ignored by the assembler as a comment). The "note" instruction defines a single note. Each note has 4 tones and a single duration. The syntax is:
note(left1,left2,right1,right2,duration)
The actual note values are periods, and instead of you calculating them yourself they are all defined in notes.inc. They all take the form "notename-octave", so c0 is a C, c1 is also a C (but an octave higher), cs2 is an octave higher and sharp. There are 8 octaves (numbered 0-7), but please stick to the lower ones (you get increased distortion in higher ones), and the available note names are:
You can also specify "rest", which plays no sound.
The durations are expressed as fractions of whole notes (easier to copy from music this way). You have:
Those that have the number 3 after them are the "triplet" versions. Those that have the letter 'd' after them are the "dotted" versions.
After each section, you MUST put the instruction "endsection".
Once you have structured your sections, you need to piece them together into a song. You do this with the instruction playsection(). You must also make sure that this part comes just after the song header. You put the label of the section you want to play inside the brackets. Finally, end the song section with the instruction "endsong". You must also make sure that you set "tempo" to something - 100 is a good start value (the smaller the number, the slower the song).
The best way to show this is to look at one of the existing files, but here's a simplified "song":
.org $0000
#include "notes.inc"
title: .db "Sample Song",0
artist: .db "Ben Ryves",0
album: .db "The REadMeIX 2005",0
tempo = 100
playsection(intro)
playsection(verse)
playsection(chorus)
playsection(verse)
playsection(chorus)
playsection(ending)
endsong
intro:
note(f0,f1, c3,f3, sixteenth)
note(f0,f1, c3,f3, sixteenth)
note(g0,g1, d3,g3, sixteenth)
note(g0,g1, d3,g3, quarter)
endsection
verse:
note(f0,f1, c3,f3, sixteenth)
note(g0,g1, d3,g3, sixteenth)
note(g0,g1, d3,g3, quarter)
endsection
chorus:
note(f0,f1, c3,f3, sixteenth)
note(g0,g1, d3,g3, sixteenth)
note(g0,g1, d3,g3, quarter)
note(g0,g1, d3,g3, sixteenth)
note(g0,g1, d3,g3, quarter)
note(g0,g1, d3,g3, sixteenth)
note(g0,g1, d3,g3, quarter)
endsection
ending:
note(d0,d1, a2,d3, sixteenth)
note(d0,d1, rest,rest, sixteenth)
note(d1,d2, a2,d3, sixteenth)
note(d0,d1, rest,rest, sixteenth)
endsection
.end
You MUST have the .end bit at the end too. TASM gets a bit confused, otherwise...
Please upload any good songs to ticalc.org - or, if not, at least send a copy to me so I can host it and include it in future releases of this software. If you need any help with the above process, do not hesitate to contact me!
To aid the writing of songs, there is a Windows-based song player in the /songs folder. See the file "ReadMe.txt" for more info.
This software was lovingly hand-crafted by Ben Ryves, currently (but probably not for long) studying Computer Science (eurgh) at Cambridge University, England. Some bits were ruthlessly stolen - i_LargeSprite is a slightly modified ionLargeSprite that ORs a sprite rather than XORs it. In fact, that's the only bit of the software that was stolen, really. The duration equates are from CalcMod, the note equates were calculated by me (the ones in CalcMod were way out in places). If you want to thank me, drop me an email or send me some Strongbow in the post. If you want to report a bug, email me or send me some arsenic in the post. I will try to fix bugs that I can replicate.