Saturday, August 13, 2016

Tonight's project - Voice

After messing around all day with finicky CAN hardware, it was nice to settle back and finish off a project I've had too little time for.
Well, I say finish, but there's still lots I /want/ to do with it. The important thing is that this is all I /need/ to do with it. ;)
Some time ago over in the ColecoVision forums at AtariAge I learned the user artrag had created a voice converter for the MSX that played back voice samples at 60Hz (so, digitized voice without needing to freeze the game). It sounded really good, and knowing the MSX audio hardware was similar, I reached out to him to see if we could port it.
He was nice enough to adapt the code, a MATLAB script, for our sound chip. We lose two channels in the process, which is too bad because it makes an audible difference. But most voice clips sound decent, especially if they are clear with no background noise. It's certainly understandable.
So tonight I finally finished the ColecoVision playback code, ran the Coleco and TI code through some tests, wrote up a VGM converter (to work with my VGM compressor, of course), and wrote up some basic documentation on how to use it.
That's all up at my web page, though I'm still waiting on the OK to post it at AA. ;)
Of course, there's also the YouTube video, giving a nice (unintentional) cross section of good and bad samples.
The MATLAB requirement is the hardest part... it slows it down a bit, and bloats it a lot, and requires a 370MB runtime (and the exact specific version of runtime, too, which bit me). I started porting it to C, but there are a few functions I need to get past (in addition to needing time). But I think it will be worth it.
Such a tool might also finally be the stepping stone we need to get some modern software for converting to the Speech Synthesizer (maybe... not sure exactly how the coded parameters work on that yet. Brute force might still be easier. ;) ).
The one improvement this tool could use is noise detection, so I hope to play with that sometime too. Right now it doesn't try. 'T' sounds are okay, but longer hisses like 'S', or even sound effects like booms, turn into random frequencies instead of playing as noise (and maybe being able to grab actual tones on top of it). But this is non-trivial, I tried a number of tricks in my own converter months ago. My converter got close, you could hear high pitched voices like Pinkie's, but I never solved the noise floor detection and eventually decided maybe it just wasn't going to work with three voices. (Testing had suggested more worked better). That's why I was pleased that this tool actually worked. :)
Anyway, I hope to use this for something... if not, it's something I always thought /should/ be possible! So it's good to see!

Friday, August 12, 2016

32k TI Carts

The folks over at AtariAge are going wild over 32kb cartridges, thanks to the "FlashROM99", which is a RAM-based cartridge that loads ROMs up to 32kb from SD card. One of the members attempted to convert my old Super Space Acer game (, but failed as the utility they used wasn't able to deal with numerous requirements of the program, like a loader that it required, or data files it used.

I decided to go ahead and take a stab at it myself... I found that there was a lot involved:

-The main program was 22.4k
-The sprite data was 3.75k
-The end program was 5k
-The title picture was 12k
-And the runtime library was 1.75kb

This was not going to fit in 32k, obviously, so the first task was compression. Some time ago I extracted the compression code from my VGM compressor ( in order to see if it worked standalone (and it did, though nowhere near as well as zip. However, it's much faster). I did a quick test, and found it could compress everything down from 45k to 27k. That seemed good enough.

After packing the files, I laid out my intention for the cartridge:

Every bank has a header through to >6040

Bank0 - >6000
    0040 boot, unpacker (1k)
    0440 SSE.pack to >A000, >13FA bytes
    14C0 SSD.pack to VDP >0800, >0F00 bytes

Bank1 - >6002
    0040 ssa.pack to >A000, >1FFA bytes
    14C0 acer_c.pack to VDP >2000, >1800 bytes
    1840  demq.pack to >2000, >066C bytes

Bank2 - >6004
    0040  ssb.pack to >BFFA, >1FFA bytes

Bank3 - >6006
    0040 ssc.pack to >DFF4, >1BFA bytes
    1330 acer_p.pack to VDP >0000, >1800 bytes

With the layout in place, I was able to create a quick script that would copy the files and pad as appropriate for the above structure. Then I wrote a quick set of functions to unpack each file into the correct place that it went.

The main catch, however, was dealing with the dynamically loaded files. I realized that all the loads ran through the runtime, a function called DSRLNK. I wrote a little replacement function that checked the calling address and then simply unpacked the appropriate data directly into memory, then returned. Since all but one of the files load at startup, it was pretty easy.

Getting the end loader was slightly trickier, but I just had to enable cheats, then enable overdrive on the emulator, and then get to the end of the game. ;)

 AORG >22B2

* on entry, WP is >209A
* copy return address to our workspace
  MOV R14,@>8300
  LWPI >8300
* now figure out who to call - there are 4 options
* R14    File    Vector
* A830 - SSD     2702
* DA0E - SSE     2704
* A656 - ACER_C  2706
* A638 - ACER_P  2708

 LI R1,>2702
  MOV *R2+,R3
  C R3,R0
  MOV *R1,R0
  BL *R0
* back to caller, remember to increment R14
  LWPI >209A
  INCT R14
  DATA >A830,>DA0E,>A656,>A638,>0000
In order for the unpacker to be able to run while switching banks on the cartridge, it needs to load to RAM. So the cartridge header (which is on all banks to ensure any startup state is okay) starts by copying the unpacker to RAM, then branching to it. The unpacker then unpacks the main program and the runtime, and jumps to THAT. The main program then requests the title screen and the sprites, and these requests are redirected to the appropriate routines in the unpack code.

Works pretty well, overall! and now it's time for bed. ;)