351

(37 replies, posted in Other Platforms)

Proteus that costs like $1000 is certainly an overkill for this.

For this particular application I didn't need to know exact cycle count or do assembly optimization. If I was to write AVR assembly code by hand, I sure would know how many cycles it takes - it is common practice to memorize opcode cycles (super easy on AVR), and count them in time critical parts when writing for 8/16 bit systems in assembler.

What I needed was just to see compiler generated code, to check if particular changes in C code makes resulting code longer or shorter, which is totally enough to estimate efficiency of edits - another common practice when writing for 8/16 bit systems in C. It is super simple task, I don't see why it should be overcomplicated like that with all that porting to other environments, using simulators, debuggers, and stuff like that. All it really takes is just a quick glance at the compiler output, which is normally fully exposed to the user. It is just an Arduino IDE's quirk that it hides the intermediate assembly.

352

(37 replies, posted in Other Platforms)

Thanks for explaination of the issue.

As for looking up to the generated code, I have my doubts about these ideas. First, I just need to see what compiler spits out, in order to see how efficiently certain C code compiles with certain C compiler. That's purely software issue, normally you don't even have to do anything to just get the intermediate assembly output. Using simulators, switching platforms, using JTAG or any extra HW is all total overkill for this. Also, I doubt that latest Arduino and AVR Studio 4.18 use the same exact C compiler with same exact options, and if this is not the case, it just won't help at all.

I have no doubts that a lot more can be pulled off with Arduino or plain AVR. Something along the lines of Casio CZ series or Korg Poly 800 (with external filter) should be totally doable. We here not trying to squeeze out all that is possible, we're just playing with concepts of porting over ZX beeper engines, with all their quirks and specifics, and maybe applying some of this experience to do like 'super' versions of those engines. And using Arduino over plain AVR is an important feature, because that's certainly more accessible platform for strangers and newcomers.

353

(164 replies, posted in Sinclair)

In general we can have Atari 8-bit and C64 stuff in 1tracker, as Game Music Emu supports both SAP and SID. For better convinience we'd need to make a 6502 assembler in AngelScript, to be able to use source assembly code instead of precompiled binaries, but at first it can be done with just binary (used to be like that before adding Z80Ass).

In particular for this synth, yes, first step would be to reverse it into a compilable 6502 source and data format description. I'm also not sure, maybe it would be easier to just make a new one from scratch, unless it has some unique hard-to-replicate features.

We can have fun and do an AY-3-8910 alternative, too. People were asking if it possible to do something like that for years.

354

(164 replies, posted in Sinclair)

A new version is up. I reworked engine selection, now it caches all engines info into files, because number of the engines got large enough to make scanning time kind of tiresome. A few minor fixes as well. Added Octode 2k15, PWM, and 2k16 flavours, so all Octodes supported now. Also added a very simple SN76489 engine (virtual, VGM export only, no player code at all).

The list slowly getting longer. Meanwhile, I had thoughts on the matter (not looking to the code, though), and here is what I think so far.

For oldest PCs that runs pure DOS, like XT/AT/386 maybe, the usual timed code approach may be viable, with a delay in the main loop that automatically gets adjusted at startup by measuring actual CPU speed. What is possible to do is limited by the speed of the slowest targeted system with shortest possible delay. So basically a little bit less than a 4.7 MHz 8088 can do, which is the same ballpark as ZX Spectrum. Engine types would be not limited in this case, all approaches should work. Music playing would stop everything else.

However, considering how vastly different PCs and their speeds are, plus the possiblity to run something in background, and that every PC has 8253 PIT to generate interrupts, more universal apporach would be to utilize the interrupts. Now we can have quite good sound loop sample rate (when it runs on a PC that is fast enough), but sound generation methods gets limited. We can either use one-change per loop engines, such as Squeaker or Octode, or PWM like with one pulse at a time (basically the PCM playing trick, just without PCM).

One issue with developing this field is that DosBox isn't terribly accurate in regards of timings and PC Speaker emulation. Considering that Pinball Fantasy sounds reasonable while many of the games listed above is not, I think that the second approach is more accessible at the moment - unless you want to work strictly with old hardware and old tools.

356

(7 replies, posted in Other Platforms)

The only 'proper' way to make 16-bit pointer on 6502 is just LDA/STA (ZP),y. Self-modifying code is another option, but that's only for systems with enough RAM for code.

Thought it may be actually useful to sketch out a simple 6502 sound routine. This is Music Box like, two 8-bit channels, interleaving, written in the dumbest way. Tested on NES:

;all referenced vars are 8-bit, located in zero page

    lda #0
    sta <CH1_CNT
    sta <CH2_CNT
    sta <CH1_OUT
    sta <CH2_OUT
    lda #55
    sta <CH1_DIV
    lda #150
    sta <CH2_DIV
    
sound_loop:

    dec <CH1_CNT    ;5 decrement channel 1 counter
    bne no_inc_1    ;2/3 if no overflow, skip through steady timing code
    lda <CH1_DIV    ;2 load new counter value
    sta <CH1_CNT    ;2 store to the counter
    inc <CH1_OUT    ;5 invert channel output polarity
    jmp skip_1        ;3 continue
    
no_inc_1:

    nop                ;2    timing
    nop                ;2
    nop                ;2
    nop                ;2
    jmp skip_1        ;3
    
skip_1:

    lda <CH1_OUT    ;2    kind of sbc a,a on carry
    ror a            ;2
    lda <CH1_OUT    ;2
    sbc <CH1_OUT    ;2 here we get 0 or 255 depending from the original least significant bit, slow, but universal
    
    sta DMC_RAW        ;4 dump it directly to DAC, other systems may need an AND here
    
    dec <CH2_CNT    ;5 the same for second channel
    bne no_inc_2    ;2/3
    lda <CH2_DIV    ;2
    sta <CH2_CNT    ;2
    inc <CH2_OUT    ;5
    jmp skip_2        ;3
    
no_inc_2:

    nop                ;2    timing
    nop                ;2
    nop                ;2
    nop                ;2
    jmp skip_2        ;3
    
skip_2:

    lda <CH2_OUT    ;2    kind of sbc a,a on carry
    ror a            ;2
    lda <CH2_OUT    ;2
    sbc <CH2_OUT    ;2
    
    sta DMC_RAW        ;4
    
    jmp sound_loop ;3=67t

Don't forget about the nasty 6502 quirk, if any branch (except BVS) is crossing 256-byte page, it adds an extra cycle. So it is better to align starting address and keep eye on it. Not that 1 extra cycle will matter a lot, but if there is complex branch logic, it will make difference.

Good. Updated the download with halved output gain version, just in case.

I confirm the issue. Seems that the output level is just too high, so adding another one brings major clipping. Quick solution is to reduce output volume of each instance of the plugin in your DAW.

359

(7 replies, posted in Other Platforms)

Radio-86RK should be even worse. It controls the speaker with DI and EI commands, and has DMA bursts constantly running in background to refresh screen and memory (so tape routines only works while display is disabled).

I guess Apple II's inability to set speaker state directly renders Phaser-like engines undoable, but on the other hand Apple II coders often use PWM techniques to get like ~8 'volume' levels, in Fuzz Click fashion.

6502 assembly is actually super easy, the trick is to switch the thinking patterns after x86/8080/Z80, i.e. from register-oriented to memory-oriented programming.

360

(7 replies, posted in Other Platforms)

https://www.xtof.info/blog/?p=807

Also, Peter Sovietov just said that he did a similar thing in the past, that plays sound through the actual PC Speaker, using WinAPI's Beep function. Too bad that newer Windows (7 and above) does not use actual speaker for this anymore. Anyways, download here.

Yet another new VSTi in my collection - plugin that allows to use a modern DAW to create the lovely horrible oldschool single channel PC speaker music, like old DOS games had when no sound card has been installed. I mean, like Monkey Island or Lotus III had.

The best part is that the end result can be used not just in the DAW like usual, but also exported as data to be used in actual programs. A QBasic player example is included, for shit and giggles.

Here is small MP3 demo

Download the plugin


A side note, this is my first plugin with GUI, programmed all in plain WinAPI. What an unpleasant experience it was.


http://shiru.untergrund.net/temp1/pcspe_screen.png

In case anyone interested, yet another unrelated but hardcore retro addition to my VSTi's library - Flopster, sample-based plugin that plays floppy disk drive noises to make 'floppy music' without having actual hardware.

364

(2 replies, posted in General Discussion)

I think everyone who tried to record rock guitar these days are familiar with the impulses, used to simulate cabinets, reverbs, and stuff. Now here is a fun idea: if you can record impulse response of a guitar cabinet to catch its signature sound, why not to do it with an old computer? We can easily record sound of Spectrum's internal speaker, and get a very similar frequency response in a DAW, and potentially in a emulator too.

I did this with various lo-fi devices just recently, but I don't have an original ZX to try. So maybe someone could do it? All that is needed is just to record one singular click (like, OUT (254),16 with reasonable quality (better-than-karaoke mic, 44100, 24-bit, minimized ambient noise).

By some reason, PC speaker music most often was limited to the basic square wave. The common best tricks were to interleave a few channels with quite horrible buzz (Lotus III, or occasionally interrupt one channel of sound with another (Monkey Island 2). Rarely a game attempted to put at least some expression into music, like Ski or Die! (slides and vibrato).

There were rare attempts to go beyond this, with true synthesizers/multichannel engines, though, which is totally possible (there is WAV/MOD/MP3 players for PC Speaker, after all), and always interesting to see. Thought to list a ones that I managed to find so far, while I'm researching this field.

Moon Patrol (1983) - a weird one, has three kinds of music, look for end stage and game over
Digger (1983)
Rollo and the Brush Brothers (1984)
Styx (1984) - no music, but unusual sounds
Music Construction Set (1984?)
Karateka (1986)
Saboteur II (1987)
Sid Meier's Pirates (1987)
Blockout (1989)
Budokan (1989)
F-15 Strike Eagle II (1989)
Fantasy World Dizzy (1989)
Hard Drivin' (1989)
Turbo Outrun (1990)
Knightmare (1992)

Should be noted that many of these videos has been made using DosBox, and it does not emulate PC Speaker well enough, introducing noticeable sound distortions in such complex routines. Saboteur II and Hard Drivin' suffered a lot.

366

(164 replies, posted in Sinclair)

I have 64-bit PC with Win7, but always compiled into 32 bit, because of compatibility issues - with Windows 32 bit programs runs fine at 64 bit, but not vice versa; performance gain for this program is neglible anyways.

The tracker called 1tracker because it has potential to support lots of platforms sharing the same front end and user interface, which in turn can be remade separately without need to adapt older engines. So that's not a question of 1tracker supporting other chips - it supports everything that GameMusicEmu supports out of the box. It is up to an engine to support some chip. I.e. you can make an engine for AY-3-8910 music, for SN76489 music, etc. At the moment I don't have plans to make engines for other platforms, as I got them all covered with other software, unlike all our countless beeper engines. Maybe sometime later.

367

(135 replies, posted in Sinclair)

Music in these games is the same indeed, pitched a bit differently, and with different drums.

I didn't look too much into Rally Cross, but by the sound and quick glance at the code it is the same engine as in Zanthrax and other games, i.e. the first version. You can guess some sampling process has been involved into making these drums, but they're not really sound like normal samples (actually pretty cool, unlike anything else).

Bubble Dizzy version of engine has clearly defined traditional samples. The code is very different, not a small tweak, but a complete overhaul. Music data format is the same, though. This and the fact that sound tone is the same, makes me sure it is indeed a second version of the engine.

368

(164 replies, posted in Sinclair)

Both AngelScript and GameMusicEmu giving me tons of warnings under MSVC 2008, 2010, 2015, and gcc. Seems it is just the way they has been made. So I guess that shouldn't be the issue.

369

(164 replies, posted in Sinclair)

In meanwhile, another fresh engine called Squat has been added.

370

(7 replies, posted in Sinclair)

Made a new engine, inspired and highly influenced by Squeeker and various utz's developments.

- 4 channels of tone, each channel has its own duty cycle
- Noise mode for the last tone channel
- Noise percussion, 9 pitches of noise at 4 volumes
- 7 non-interrupting sampled drums

It is implemented in 1tracker (silent update, please redownload), complete with drum samples importing.

371

(164 replies, posted in Sinclair)

Tracker does not use any TTF fonts, only raster ones. Yes, resources is not included into the source archive, sorry. Will change it later.

The second error is weird. Looks like something related to AngelScript internals.

372

(1 replies, posted in Sinclair)

Just in case anyone will need it, came up with a kind of universal noise routine. It is strongly based on utz's noise generator with rlc h. Allows to control pitch, volume, and duration of a noise burst.

    ld hl,0                ;noise accumulator
    ld de,#2174            ;utz's rand seed
    ld bc,#0101            ;noise pitch, #01 highest, #ff (#00 actually) lowest
    exx
    ld bc,1000            ;noise duration

noise_loop

    exx                    ;4
    dec c                ;4
    jr nz,noise_skip    ;7/12
    ld c,b                ;4
    add hl,de            ;11
    rlc h                ;8        utz's noise generator idea
    inc d                ;4        improves randomness
    jp noise_next        ;10
    
noise_skip

    jr $+2                ;12
    jr $+2                ;12
    nop                    ;4
    nop                    ;4
    
noise_next

    ld a,h                ;4
    
noise_volume=$+1
    cp #80                ;7    noise 'volume' here, #80 max, less is lower volume
    
    sbc a,a                ;4
    out (#fe),a            ;11
    exx                    ;4

    dec bc                ;6
    ld a,b                ;4
    or c                ;4
    jp nz, noise_loop    ;10=106t

373

(164 replies, posted in Sinclair)

Reverse enginereed and added the other Lyndon Sharp's engine, from Bubble Dizzy. Also reworked support for the first one, renamed it to lyndon89.1te (if you have modules made with the old version, just edit the module text, replace engine name there).

Thought to make a note on the row transition noise. There is a way to minimize it. The idea is to avoid row transitions as is. Rather than storing song as a set of rows, with constant skipping of empty fields, store delays between any actual changes that is taking place. This should keep the sound loop tight, and longer gaps when actual changes happens will be masked by the fact that these changes actually change/restart a note, or trigger a drum, i.e. introduce a major change in the sound anyway.

I.e., rather than:

C-1 ...
... ...
... ...
... ...
... C-2
... ...
C-1 E-2

have:

C-1 ... > run sound loop for four rows without parsing anything
... C-2 > run sound loop for two rows
C-1 E-2

375

(135 replies, posted in Sinclair)

Wow, totally missed it too. Really cool one. Seems to be next version of the Lyndon Sharp's engine. Thanks a lot for pointing out.