151

(16 replies, posted in Sinclair)

That's nice, 150 bytes here and there would make an extra K. How long does it take to decompress?

152

(16 replies, posted in Sinclair)

Well, Freezing Point data is certainly not 94K large. You're packing the source text file for some reason.

The binary data is 16714 bytes large, 2768 bytes after packing with the apultra. You can try ZX5 on this data (attached).

153

(16 replies, posted in Sinclair)

Yes, that was Shrinkler, a few versions in fact. No, haven't tried ZX0, because there is a large test table for all Z80 packers, and ZX0 shows worse results for all test datasets there than apultra.

154

(16 replies, posted in Sinclair)

I used apultra to pack everything, including players. Players and music data were packed separately, so players get reused. I also tested some even better packers, but they would take like half a minute to decompress in the worst case, which is unacceptable.

Even with the best packing, I needed a large buffer for the largest unpacked song, it was nearly 19K. At this point it couldn't fit at all.

I had to:

- Place my code as low as #5b00, disabling the BASIC interrupt handler completely
- Overwrite the screen drawing code with the song buffer
- Decrease the two largest songs

In order to decrease the largest songs size, which happened to be Freezing Point and Geostorm, I first made a function that optimizes out the empty rows by reducing the speed of a row before (recursively, as long as row speeds allows). This optimization can be applied to any song in 1tracker now. This helped a bit, but still wasn't enough. So I also had to modify wtbeep and SquatM formats.

In the wtbeep, I now omit the 0 byte for rows without a drum (it is now triggered by the bit 6 of the control word). Saves a bit of room.

In the SquatM, I reworked the way how the dividers stored. Instead of the normal LSB/MSB order that is easy to read with POP I stored them in the MSB/LSB order, and used bit 7 of the MSB as the note rest flag. The LSB is omited for note rests. This of course made the song data parser very suboptimal, but the Sqeeker-like design does not suffer from row transition noise much, and I gained the remaining bits of the RAM.

The largest songs remained the same, but I saved a couple K this way. Freezing point is 16714 now, and Geostorm is 15809 (2768 and 2500 packed).

155

(16 replies, posted in Sinclair)

A small behind the scenes post about this release.

156

(16 replies, posted in Sinclair)

Thanks, guys!

Interestingly, both Geostorm and High Orbit started as NES tracks, they were half finished sketches (half length of the finished versions) written for a game that never happened, lying around since 2017 I think. I thought they won't translate into 1-bit well, because the NES of course used volumes, duty cycle, slow attacks, samples, and so on. But it turned out to be the case when moving a song sketch that is just stalled in one format into another format made it shine.

Nothing special, just thought to share. Got all my Spectrum 1-bit stuff that has been made since 2016 and released as a compilation, in audio format and as a ZX Spectrum 48K program. No new songs here, everything has been released previously, it just got packed into a nice package.

Bandcamp
ZX Spectrum program
Youtube

158

(37 replies, posted in Other Platforms)

Sure, you can upload it. WTFPL/CC0 it is.

159

(5 replies, posted in Sinclair)

The engine support has been added to 1tracker. Time to push the boundaries a bit further!

160

(164 replies, posted in Sinclair)

v0.32 is out, with many improvements. Relatively major changes in the front-end code here and there. wtbeep and Squat family support got updates. Most importantly, Velvet engine has been added.

161

(37 replies, posted in Other Platforms)

Sorry, I don't use Github, so unless some uploaded it there, it isn't there. And I doubt anyone did that.

162

(115 replies, posted in Sinclair)

The full results are up, here are the beeper ones:

ZX Spectrum Beeper Music

1.   7.51   Freezing Point by Shiru
2.   7.11   Geostorm by Shiru
3.   7.03   March Of The BioMech by Tufty ^ 1bit Forum
4.   5.97   drum'n'halt by utz ^ irrlicht project
5.   5.76   Rekcart by AER
6.   5.61   babka_dance by AER

163

(115 replies, posted in Sinclair)

Just seen the results in the stream. 1st and 2nd are mine, Freezing Point and Geostorm. 3rd is Tufty's March Of The BioMech. Congrats, Tufty!

Should say I was expecting the utz's drum'n'halt to get the 1st, it was so fresh. Wish I would make something like this. And I was expecting to get 3rd with one on mine's, as Tufty's stuff is great and strong as usual - it sounds very powerful and not so beeper'y at a good volume.

Regardless of the results, great job as usual, guys! Beeper is the real winner again!

I was thinking to get it working on the 2600, too, using a trick to get a reasonably well tuned notes, but left it out for possible future updates, otherwise it could stay in the unreleased limbo for even longer.

Released the whole source code for PeskyTone, the music player with VIC-20, C64, and NES support. I also have a half-working Plus/4 support, but there is another mysterious issue that I couldn't figure out yet, so it is omitted for now.

I think it is just fine, it has everything that is needed and the schematics can contain just a battery, chip, and piezo speaker. It has just a half of the ATtiny10 power, but for much lower price. The only problem is that 150 has OTP memory, i.e. it is can be programmed only once. There is 154 that features Flash memory instead, the price is tad higher.

I'm still trying to figure out the actual LFSR implementation to get proper pitches.

While I was blindly experimenting with the extracted data trying to figure how to make it work, Ken Shirriff made a huge post full of precious information on the chip internals. In fact it has been explored back in 80s in an electronic magazine. So now it is totally possible to emulate the thing. I think the Arduino will be a good host - readily available, easily programmable. A more hardcore option would be an ATTiny implementation in assembly, it would function just like the original - one chip and no external components besides the battery and the speaker.

The arrangement of the chunks in the song ROM is likely visually linear - basically first 64 bits of the data is bit 0 of the whole song, then next 64 bits are bit 1, and so on (there is binary decoder to the left from the mask ROM field, and its control lines seem to be parallel). So it should look more like:

1000001001111101000000100111110100000100111110111100010001000001
1101010110100100110101011010011010101011010011000011101110111110
1000000110000010100000011000001000000011000001000011010011011110
0111110011010000111111001101001011111001101001011010100101101010
1111111110111111011111111011111111111111011111101111111111110110
1111111111110111111111111111011111111111111011110111011101111111

This way it really looks like the duration is encoded in the two bottom rows (two top bits).

In order to make a software emulator with very authentic sound and limitations, we need to read out the contents of a chip, and make a parser that would yield the melody that is contained in the chip.

There is a bit older but high resolution photo of the UM66 die, so I used it to read out the mask ROM contents visually. This is the UM66T-19L variant that contains the For Alice (Für Elise) song. This video features a music card with this song, I guess that's is that encoded in the binary data below.

We know from the die photos that the LFSR is 7 bit, but the taps are unknown. There are different possibilities on that, and I can't figure out the actual one from the die photo (yet). The input frequency is presumably 32768 Hz, no intermediate dividers. There is a 9 bit divided (or that's a multiple of 9) for the clock frequency that somehow gets converted into the note durations (using another LUT), though.

One ROM on the die is 7x16 bits, that's presumably a pitch LUT for 16 pitches with 7 bits to initialize the LFSR. The weird part is that there is 3 of 16 entries are all 0. The addressing is horizontal (0..15):

0000110001000011
0010001011110000
0001100001010101
0011110000100010
0011001110110101
0010100011000011
0011110010100010

Another ROM, the largest on the die, is 16x24 bit. That's presumably the song data that is presented with 6 bits per note (4 bits for pitch, 2 for duration), 64 notes total. 16 is 1/4 of the sequence length, so the addressing is at partially horizontal (0..15 in the lowest 4 bits of the address), but the arrangement of the chunks is unknown:

1000001001111101
0000001001111101
0000010011111011
1100010001000001
1101010110100100
1101010110100110
1010101101001100
0011101110111110
1000000110000010
1000000110000010
0000001100000100
0011010011011110
0111110011010000
1111110011010010
1111100110100101
1010100101101010
1111111110111111
0111111110111111
1111111101111110
1111111111110110
1111111111110111
1111111111110111
1111111111101111
0111011101111111

Yet another ROM is 4x4 bits. That's presumably the note duration ROM, although presumably a song position is encoded as 4 bits pitch and 2 bits duration. Not sure why there is 16 bits then:

0110
1000
1010
1001

May be a very interesting read to some, the reverse engineering process of a music greeting card chip. There are numerous chips of this kind, but they're function much alike, so it is very likely they're all share a very similar design. Read the original tweets or a condensed thread.

TL;DR - it is a hardwired machine with a 64-byte ROM that uses 4 bits for pitch and 2 bits for duration. No real computations are going here, it is not an MCU of sorts, just a very simple state machine. The most interesting part is how it produces the frequencies. I was wondering on this matter in the regards of the Game & Watch, with its 32 kHz oscillator, and it seems this one uses the same trick: an RC generated 32 kHz source get divided with a 7-bit LFSR instead of an actual counter, which is also cheaper on the transistor count. Actual pitch for the 16 notes is pre-programmed with the values loaded to the LFSR, so it is not square wave, but some bit patterns unique for each note.

As it is a mask ROM hardwired non-programmable chip, we can't really reprogram one for our needs. However, we can emulate it with a modern MCU, and drive it with a custom 64-byte sequence. Like, the tiniest ATTiny10 should be able to do the trick easily (and it has 1024 bytes, enough for a dozen of the short songs).

Side note, SjAsmPlus actually has support for 8080 with Z80 syntax, it basically limits valid supported opcodes to the 8080 subset. Activated with --i8080 flag. As there isn't many (if any) good modern 8080 cross assemblers, it comes very handy.

172

(19 replies, posted in Sinclair)

A note on this issue regarding to 1tracker. Most engines will survive a quick and dirty fix. You can open a *.1te file with a text editor, find there 'out (#fe),a' line, and add a 'and 16' line just before it. It will work in most cases, although a couple of engines may break. The downside of this fix will be a bit reduced pitch and play speed.

Some engines can have pitch issue corrected, although not all of them - find a definition of 'cpuTime', and subtract 7 from the value. If there was a few 'out (#fe),a' lines, add 'and 16' to each of them, and subtract 7 for each one as well.

This is a temporary solution, as it is uncertain if/when we will be fixing the issue. At least I'll add a note for each engine that is currently not compatible with +3, I guess.

173

(19 replies, posted in Sinclair)

Wow, that's unexpected. Some of my engines guilty with the same thing, though. Squat, for one. Easy to fix, though, but it'll reduce the internal sample rate a bit.

I recall some years back there was a guy who was talking a lot about this possibility of getting four output levels on the classic 48K beeper, and proposed to use it somehow in a beeper engine. However, as they're pretty close to each other on the extreme ends, no one figured out any useful application for such a feature.

Actually, even if there was a true 2-bit DAC with proper evenly spread levels, I'm not too sure what advantage it could have over 1-bit - a two-channel engine with 'lazy' mixing perhaps, but that wouldn't give a major speed advantage, or extra opportunities for more unusual synthesis techniques. Maybe I'm wrong.

Curious little quirk, nevertheless.

175

(19 replies, posted in Sinclair)

A guy reported a very weird issue with this engine. It is completely messed up on the ZX Spectrum +3. Not too sure what causes it, but the result looks like it runs in the slow memory. Booting in 48K mode does not help, I suppose it should have a fast RAM page at 8000 in the default configuration anyways?