(129 replies, posted in Sinclair)

Another compo is nearing: Quantum Oscillation Party

This is a weird one, but may be a nice fit for the beeper: noise art. Includes an oldschool computer noise music, which is music made of noises. Seems to be a good case for the noise channels in our beeper engines, if you're in the experimental mood.


(129 replies, posted in Sinclair)

Three sample channels is a good thing, but I think we need to intermix simple timbres such as the regular square wave or pin-tone with samples of a long duration that lasts for a few rows - drum pieces, some instruments. The problem is that to get a clean square wave it either needs to be encoded for a long length (maybe a pattern even), or some kind of sample looping considered, which is cycle-expensive.


(129 replies, posted in Sinclair)

I was thinking about a Sqeeker-type engine with two pitchable non-interrupting sample channels. At least a couple tone channels wouldn't hurt, and the pitchable samples that can tune in to proper notes should open up a whole new lot of possibilities.


(129 replies, posted in Sinclair)

Great work everyone! Congrats to utz! The sampled sounds are so clean and punchy in this one.


(129 replies, posted in Sinclair)

No voting results yet, but it is sure a win in the engine diversity category this time. Like, each of the six entries used a different engine, including some of the lesser used. Neat!


(129 replies, posted in Sinclair)

I'm in. Got some older stuff finished for ya.

Actually, a bigger update. All plugins were cleaned up and updated. The output levels normalized between all plugins (were all over the place), all synths got the modulation setting (depth, speed), some got extra velocity or modulation targets.

Legacy code is dropped out, so a bit of incompatibility with the older versions got introduced, so use old builds for older projects.

A small update:

- sweepsynth got wrap around options and expanded sweep speed range
- pulsesynth got a few extra oscillator mixing options, much similar to Phaser4

I'm good, thanks! I'm from Russia, most of foreign social networks were blocked here for a long while, and the ways to get around it is getting more fiddly lately. And yeah, I also stupidly busy during recent months too. So I suspended my Twitter account for some time.


(6 replies, posted in Other Platforms)

Heh, the more fun is that Sol-20 Music System has been 'borrowed' for the RK86 back in 1988, and published as a hex dump in a paper magazine. It is even still called Music System (MS 3.2).


(5 replies, posted in Sinclair)

I expected the challenge to be the flexible channel layouts and PWM drums, but in fact yeah, I forgot I already handled such configurations. However, there is a less expected issue, both ulasyn and phaserF use a macro to calculate their filter tables. My assembler is certainly not up to parse that, so I guess, I'll have to offload table generation into the engine script. Anyways, seems to be doable.


(6 replies, posted in Other Platforms)

Oh my, I actually never thought it could be done this way, via in/out. Never looked up ZX81 either, as I expected it to be just a regular output register.

So I guess they're connected tape output just to the IOWR, because it is the only writable I/O port, and thus saved a trigger/register. And when extra devices with writable ports added, you'll get a buzz on the tape output when they're accessed.

Another weird method of controlling a speaker is found in the 8080-based Soviet DIY computer RK86. It lacks any interrupts whatsoever, so EI/DI control the speaker.


(5 replies, posted in Sinclair)

Still, it is very impressive. I wouldn't say the sound quality is any bad, we've had worse, and it is certainly on a new level.

This one feels to be tough to make into 1tracker, but anyways, I'll try.


(9 replies, posted in Sinclair)

I'm certainly up to try to implement the 1tracker version, just waiting until it get settled down with the features.

The cheapest I found locally as a DIY module is $7.7, and it is about the same at AliExpress, from China. Yeah, a bit on the expensive side, but luckily, it is easy to replace with the classic S series (a regular ESP32 with the Xtensa LX core), which is cheaper. The 1 euro is likely was a bulk order price for bare chips, not modules.

Anyways, I got a couple to try it out and see how fast they are for this application. There are two resource heavy things: LCD/TFT/OLED screen update, which is done via SPI (serial), and the VM/emulation core, which is going to be simpler than for a proper emulator, but still, lots of RAM fetches. It will define how fast the virtual Z80/6502 is going to be, and I guess it needs to be at the least a double-triple of the regular Spectrum speed to make the idea feasible, more the better.

Here is an updated draft v03. I picked up some ideas from conversations with friends, so the thing shapes up nicely, into something that can offer not just internal architecture, but some interesting external gimmicks as well. For the user it is dual D-Pad, stereo sound, light effects, and cartridge.

Also, started to consider to use a RISC V powered MCU (ESP32-C3 has RISC V and WiFi in a single package). That would be a nice feature to feature an open core in an open console.

Sure, I'll keep it reasonably powered, not too powerful - at least some challenge will be there.

The thing with VM is that any MCU and screen can be used. Arduboy and most of the crowd is tied to once picked type of MCU (particular revision even!) and screen (also of a specific revision!). It is only possible to change the components by modifying all the games in the wild. VM allows to untie the platform from the hardware. Basically it starts the life as a specification that can then be implemented in many different ways. If one MCU gets obsoleted, the VM itself can just be ported to a newer one, and all software will work - just like we're playing Spectrum games with emulators.

WiFi for uploading games and backing up the stuff is easy on the ESP8266 or ESP32 MCUs, they're made exactly for this purpose. If other MCU is picked, 8266 can just be added as a secondary chip to handle the task. It is also can be done for a particular implementation, and dropped in another.

Now the between-units connectivity, like a multiplay of sorts, is a whole different matter, I'm avoiding to get into it at the moment. I know it is doable with the ESPs as well, but the exchange rate isn't too fast, like 0.1 seconds lag at best.


(9 replies, posted in Sinclair)

Oh my, now that is definitely some forbidden black magic. I can't wrap my head around it at the moment, but it sounds totally unbelievable for the beeper.

To clarify, the point of picking an existing command set is the possibility of hooking up an existing C compiler (or a BASIC compiler, perhaps, like Boriel ZX Basic), which would make it much easier to use for those who aren't into the assembly code programming.

AVR is a good idea, but there are some minor hiccups with it. One is that it is a (modified) Harvard architecture system, with code and data split into separate spaces, and not intended to be self-modified. Another is that while I can easily re-target Z80 or 6502 C compiler to this design, modifying a modern gcc seem to be much more difficult. Another thing with Z80 is that it has the I/O space, but anything else will require to have memory mapped registers, and it makes the architecture less clean. Like, the regs has to have a reserved memory area.

I considered 6502 at first, because it is much easier to emulate, thus VM would be much faster. I believe it is a good pick, but I kinda felt that 1-bit stuff is more related to Z80.

Another crazy idea I had was to actually have a few VM cores to run different binaries within the same specs. Maybe it is actually a good idea, like, just imagine - you can pick Z80 or 6502 or AVR instruction set, and implement the same code for the otherwise same platform in either of the instructions. What a test bed for direct comparisons (sans the reduced T-states). Also enables a wide choice of the existing tool chains.

As for the sound system design, I can actually join a few approaches into the same setup. I drafted the 8x 1-bit system, but I can also just drop in 8 registers to auto reset each channel, it is very easy and will look just as clean.

A preliminary vision of the possible hardware implementation. It may vary, depending on the MCU and the screen types, but it is likely a horizontal layout, and built around an SPI or parallel interface LCD/OLED/TFT screen of reasonable dimensions (not extremely tiny).

On-board Flash memory and WiFi connectivity are likely. A standardized shape/slot/loader for external SPI memory is a must, because all modern DIY devices like this missing any footprint in the history, and it is a cool thing older platforms had, but is optional for use.

The design is aimed to the acrylic laser cutting and PCB routing rather than 3D printing, as it gives it nice clean look and it is accessible enough.


A crude draft of the system specs I envisioned so far:

virtual cpu

z80 with 1-state opcodes

the system will have a cap of X opcodes per frame, depending on how many
ops can be performed on a reasonable MCU for the initial hardware


whole 64K is RAM, some part of it can be configured as video memory


everything is loaded as an overlay file, either from internal device
memory or PC file (in PC emulator), or from an external storage

the overlays are stored as a number of *.1bo files, the primary one
is *000.1bo, that is loaded first, and *001.1bo to *255.1bo can be
requested from the code

a file may contain any number of blocks of any size. a block has a
header that is 16-bit length, 16-bit loading address that is followed
by the [length] bytes

last block is length=0 and starting address (if 0, ignored for requested
overlays, otherwise control transferred to the address)

this way overlay can contain only a small piece of memory, like level


128x64 monochrome, very basic system that allows double buffering, scrolls,
resolution doubling and screen splits

video memory bytes are vertical oriented, 0 at the top

there are 64 line that are represented with 128 sequential bytes in the RAM,
one of bits in each one (e.g. bit 0) contains the pixel state

all 64 lines can be configured to point to any RAM location, and a bit mask
can be set to pick the bits that will set screen pixel if any of the pixels
in the mask are set. bit mask also allows to make varied effects, like,
dynamic vertical resolution decrease

video configuration is done by selecting a line with an out, then outing the
three bytes to their respective ports. the new configuration will only be
applied at the beginning of a new frame, so no mid-frame changes will take
effect (for varied HW implementation compatibility reasons)

one possible configuration is to set each line to a 256 byte boundary,
this gives 256x64 (or taller) buffer

by changing the bit mask it is possible to scroll vertically

by changing the address it is possible to scroll horizontally

in the Z80 code, inc l to go the next pixel horizontally

in the Z80 code, inc h to go the next pixel vertically

alternatively, the lines can be packed tighter, set to a 128 byte boundary,
so inc l is still useful, but add hl,128 is needed to go the next line


everything is mapped to the ports, no memory mapped registers

00 screen control, write set config (reserved at the moment), read
allows to sync up to the screen update, a 8-bit counter gets incremented
at beginning of a new frame

10 buttons state %10YXUDLR (0 and 1 are main buttons
   XY are left/right shoulders)


20 raster line number, changes get applied at beginning of the next frame,
   no multicolor techniques allowed
21 raster line lsb
22 raster line msb
23 raster line bit mask

30 sound output
31 sound output fifo, write set length 1..256 (0) bits, read returns actual
   current length of the buffer, to detect if it is the time to feed some more
32 sound output sample rate lsb, in hz, something about 8000..16000, maybe higher
33 sound output sample rate msb
34 sound mixer left
35 sound mixer right

40 timer nmi config
41 timer nmi lsb, freq in hz
   (not in t-states to avoid issues if overclocking is applied)
42 timer nmi msb

50 timer irq config
51 timer irq lsb
52 timer irq msb

e0 overlay loading (not banking, takes some time), basically out an overlay
  number to request loading

f0 in-device save/load, for game saves
   write 1 to request load
   write 2 to request save with the parameters below
f1 save slot (a few slots)
f2 save area lsb
f3 save area msb
f4 save length lsb (probably limited to a few K)
f5 save length msb

Recently I was messing around with the tiny DIY consoles a lot, such as Gamebuino, Arduboy, and ESPboy (even made a tracker for the latter). This led me to thinking how much things feels wrong in most of these, or that I'd like to be done in a different way. For one, they're all tied to a proprietary hardware that gets modified or obsoleted as the time goes, and today it is quite difficult to make a correctly functioning Gamebuino or Arduboy without a kit, using of the shelf parts. Like, you have to burn a custom bootloader with an ISP programmer, and the bootloader is not compatible with the modern AVR chip revisions - does not exactly feel like an Arduino based project anymore.

Eventually I came up with the thought: why not design a platform like these the way I'd like to see it - I totally capable to do it. Hence this idea was born, to make a virtual platform that is strictly 1-bit in the media output (visuals, sound), much like Arduboy, but that is prone to the hardware compatibility issues, like CHIP8, and can be both interesting OR easy to program. I plan to design it as an emulator (virtual machine), then make my own custom hardware implementation (MCU based, emulation driven as well). All open source, of course.

I would call this thing 1-BOY and steal the 1-bit forum header design for its own logo. I'm totally sure not many outside our community will get interested with it, but whatever. We deserved to have our own 1-bit platform, after all.

The basics are:

128x64 1-bit display, can be LCD, OLED or TFT in the hardware implementation (unified frame buffer access only, no direct control)
1-bit stereo sound
8 buttons (D-Pad, A/B, L/R shoulders)
Z80 core at some higher-than-normal frequency
64K of RAM
Programmable interrupts
Some extras

Yep, much like ZX Spectrum or TI calcs, but in a portable console shape and DIY. It could be programmed directly in Z80 assembly, as we like it, or in C using SDCC and a custom library to handle sprites etc. It does not consider huge games, because no one is going to make those for such a basic device anyways (but an overlay loading is considered in the extras).

Now the interesting question is the sound system. I can see plenty of ways how to design it in a most interesting way to explore it later - we basically can have anything we couldn't with the real hardware. However, unlike the hardware that could go insane bit flip frequencies, it will be always affected by the sample rate, and considering the hardware version of it is going to run at a less than stellar cheap MCU at first (something like 160-240 MIPS), it won't be too high.

Possible ideas I've had. I'm not sure which one to stick to:

1) A register with 8 output bits, each acting as a beeper. Two additional registers to control each of the bits, to direct it to the left, right, center, or mute. Like, %BBBBBBBB (8 beeper output), %LLLLLLLL and %RRRRRRRR (routing to L/R outputs). This way we could have 8 channels without the need to mix them, they're summed at the output. That's the old PDP-1 inspired way that had 4 mono channels in the early 1-bit music experiments.

2) Just two output bits, L/R, but with an optional reset counters that will drop it back to 0 after a given number of ticks since writing an 1. Basically a hardware narrow pulse technique. That is, you write 200 in the Lcounter, write 1 to the L channel, and it stays 1 for 200 CPU t-states.

3) Alternative implementation to 2, instead of traditional output bits just write a value to a counter, and it'll set output level for the given amount of time. 255 to keep 1 indefinitely, 0 to force output reset.

4) A buffered beeper. L/R bits, but you can feed them with new bits at any rate, and they'll get played back at a fixed rate. That's probably the most robust system for an emulator-based implementation, as we can set that fixed rate to, say, 44100, matching the actual sample rate, and we can also have a modified Z80 core with all t-states reduced to 1. However, I can't get my head around it yet, how difficult it would be in the actual use.

5) Any other ideas that would move sound generation away from Z80 core. I believe this is less interesting approach, as it leaves not much to explore and exploit. Something like a 3-8 chained PITs, much like PC speaker, but multichannel and with ability to set pulse duration.

A programmable timer, like, NMI or IRQ, can be also set to the emulation output sample rate (that may be configurable), so the software sound synth could be interrupt-driven, given the virtual Z80 have enough time to run it that frequent. But it works more towards Squeeker and Phaser like engines, kinda leaving out the pin pulse ones (depends on the sample rate).


(10 replies, posted in Sinclair)

Oh, sorry, here's the text dump. You can dump any module like that with File > Export command stream > Export text.


(10 replies, posted in Sinclair)

Wow. Sounds reasonable!

In meanwhile, I found one actual FUR module for the QuadTone engine. May come handy for tests.


(10 replies, posted in Sinclair)

Furnace does feature some kind of debug stream dump, which may be used for conversion purpose, although I'm not really understand what's going on there. For QuadTone it looks like this:

# Furnace Command Stream

system: ZX Spectrum (beeper only, QuadTone engine)

tickRate: 60.000000


>> TICK 0
  0: NOTE_ON 45 2
  1: NOTE_ON 40 2
  2: NOTE_ON 24 2
  3: NOTE_ON 31 2
  4: NOTE_ON 24 2
>> TICK 12
  0: NOTE_ON 57 2
  1: NOTE_ON 52 2
  2: NOTE_ON 24 2
  3: NOTE_ON 31 2
>> TICK 24
  0: NOTE_ON 43 2
  1: NOTE_ON 41 2
  2: NOTE_ON 24 2
  3: NOTE_ON 31 2
  4: NOTE_ON 24 2
>> TICK 36
  0: NOTE_ON 55 2
  1: NOTE_ON 53 2
  2: NOTE_ON 24 2
  3: NOTE_ON 31 2
>> TICK 48
  0: NOTE_ON 41 2
  1: NOTE_ON 43 2
  2: NOTE_ON 24 2
  3: NOTE_ON 31 2
  4: NOTE_ON 24 2