I haven’t done anything specifically related to Vectorblade for over a months now.
I am thinking about stuff to “fill” it up a little more besides pure gameplay. Little stuff that will make a complete “round” package.
You have seen an Intro Test, I have done the disk, I have done a new/seperate highscore editing (not shown yet) – and I have improved the tile base engine to be prepared to do collision detection (which might lead to an extra “game – gem” – or not).
I will probably use very little of what I have researched so far – because I don’t realy fancy it anymore …
The “sample gambling” described in this blog entry also originated in that search.
Sound Samples 1
In general – the Vectrex can play digitized sounds. The first game to support this was Spike:
“Eeek, Help, Spike!” – “Oh No, Molly!”
On the technical side this is possible since the DAC output can be (electronically) connected* to the amplifiying hardware.
If the sound samples are in the correct format, and the sample bytes are output frequently enough to that hardware (e.g. 8000Hz sample rate -> 8000 bytes per second to the output…) – than you can listen to sampled sound.
I have never taken measurement – but I think Spike might have a sample rate of something between 3000 – 4000Hz.
The sound format is: PCM unsigned, 8 bit.
The challenge with playing samples is the above “frequently enough”. If we take the example from above (8000Hz), a digitized sound byte must be played every 188 cylces.
6809 clockspeed 1.5Mhz
-> 1 secound = 1500000 cycles, 8000 sampels per second ->
1500000/8000 = 187.5 -> every 187.5 cycles a sample must be played
Playing a sample itself (reading the byte, preparing output etc), takes also some cycles, lets say the sample output takes about 60 cycles. In summary you than:
- have only 2/3 of cycles for the rest of your program
- the program must be interrupted each 188 cylces for about 60 cycles
- due to technical limitations the sound output can NOT be done while the vector hardware is active in any way
These are pretty steep restrictions – this is one of the reasons, why you see very few programs, that make use of samples. And even less programs that incorporate digitized sound during gameplay.
For undisclosed reasons accessing the audio hardware does not work properly on newer vectrex versions. The so called “No Buzz” Vectrex do not play digitized sound correctly – they do still play the sound, but it is even in full volume only barely audible.
Sound Samples 2
Especially above mentioned “additionally” was a thing that always bothered me. For quite some time I was thinking:
“sample playing must also be possible by using the PSG chip”.
Some weeks ago I started trying that out, I wrote a small program, that would output samples to the PSG chip.
– sound samples are (more or less) volume levels. My thought was – “if I output these volume levels to the PSG – I ought to be able to play samples using the volume registers”
My first tryouts were quite bad.
I could hear some “scratching noise”, that was in the rythm of the digitized sound that I wanted to play – but that was about it.
Several tryouts later I discovered the reason: I had to use a different sample format.
I don’t exactly know why, but playing digitized sound via the PSG you have to use the format:
During my search I also found a couple of interesting links:
Playing samples on the PSG
Playing samples on the PSG
Crystal clean PCM 8bit samples on the poor PSG
Which provided some information.
The volume levels of the PSG are encoded in only 4bit. Thus the sound format “complete” is: PCM signed 4 bit.
The volume level is based on a “logarithmic volume scale” so in reality the above mentioned 4 bits are more something like 2.5 – 3 bits. The number of volume levels available restrict the quality of samples.
The gist is by using the PSG as digitized sample output:
– negative: reduction of sample quality from 8bit to about 3bit
– negative: the playback routine needs more cycles (PSG-Registers are harder to access than the audio hardware)
– positive: the sample size is only half as big
– positive: playback is “constant” on all vectrex
– other: playback is a little bit softer than audio hardware using samples on “buzz” machines
On the above pages it is mentioned, that the quality can be enhanced by adding sound levels of more than one PSG channel.
I tried that – and failed. That might be prone to my programming skills – but I rather suspect, that due to the “complicated” way that PSG-registers are accessed in the vectrex hardware, that the timing with which the volume levels are put into the 3 PSG channels differs to much to produce clean samples (30-40 cycles needed for each individual channel).
On above pages it is suggested that the volume levels from the samples could be “translated” to corresponding PSG levels (linear versus logarithmic). I tried that also – which resulted in an audible pessimation rather than an optimization.
The next Vide version will feature a method to build samples and generate a player for above PSG “Samples”.
Following some of the used source code:
Write data in B to PSG register in A, here you see why it is more complicated to write to PSG registers.
WRITE_PSG_DIRECT macro STA <VIA_port_a ;store register select byte LDA #$19 ;sound BDIR on, BC1 on, mux off _ LATCH STA <VIA_port_b LDA #$01 ;sound BDIR off, BC1 off, mux off - INACTIVE STA <VIA_port_b LDA <VIA_port_a ;read sound chip status (?) STB <VIA_port_a ;store data byte LDB #$11 ;sound BDIR on, BC1 off, mux off - WRITE STB <VIA_port_b LDB #$01 ;sound BDIR off, BC1 off, mux off - INACTIVE STB <VIA_port_b endm
This macro must be called whenever we have “time”.
It waits for the next timestep, where a sample must be played, outputs the sample nibble and restarts the timer.
(this can be optimized)
NEXT_DIGIT_BYTE_FASTER_NO_I_4bitPSG macro ; name of macro ; load current digit byte and increment counter WAIT_FOR_NEXT_DIGIT ; otherwise we wait till the last played ; sample-byte is finnished CMPY digit_end_pos ; if it is zero, than we are finnished BNE sound_not_done ; with this sample, otherwise we continue further below ; if we are done, should we restart? sound_done: LDA digit_looping ; is this sample a looping one? STA digit_is_playing ; store it to is_playing BEQ timer_restart_only ; if none looping... we are done ; but we still must use the timer ; ok, for restart, we only change current position LDY digit_start_pos ; load the start position ; this is the end_position of the sample, ; since we go backwards BRA timer_restart_only ; and restart the timer, next byte ; is played next round... ; here our normal 'digit_byte_playing_section' sound_not_done: tst digit_oddEven beq doFirstNibble LDb ,Y+ ; load the next sample_byte to A andb #%00001111 clr digit_oddEven bra doDigitOutput doFirstNibble LDb ,Y ; load the next sample_byte to A lsrb lsrb lsrb lsrb inc digit_oddEven doDigitOutput ; to reg 8 (Amplidtude) lda #8 WRITE_PSG_DIRECT timer_restart_only: RESTART_TIMER ; restart timer... makro_rts: endm ; end of macro
I have put a small example together:
A sample is played and a frog displayed.
The sample has a sample rate of 8000Hz and is output via PSG using 4bit samples.
The time between samples (in cycles) is about the above mentioned 188 cycles.
The time needed for playing the samples (in cycles) is about 70 cycles – thus about 110 cycles are left to draw vectors.
The vectors displayed are drawn with a scale of 50.
I was not yet able to display raster text reliably.
To put a sample byte to the amplifying hardware:
– you have to use the VIA
– the DAC output has to switched to “audio hardware”
– this is done using the MUX connected to VIA
– to select MUX settings Via Port B is used
– bit 0 is the MUX enable bit (zero active)
– bit 1+2 selects the “destination”, bit 1=1 and bit 2=1 selects the audio hardware
– first you set 11 to bit 1 and 2, and prepare the MUX to send bytes to the audio hardware
– you set the DAC value using VIA port A
– you set VIA port A to the sampled byte
– than you set Via Port B bit 0 to 0 (zero) -> the audio hardware will receive DAC values
– > you just put one sample byte to the audio hardware
– (don’t forget to clean up the VIA Port B)
Interesting that the “vectrexy” emulator fails to play any audio with this binary! (I’ll play it on the hardware tomorrow – it was already quite late tonight when I saw this post)
Vide will play that ‘correctly’ with versions 2.03 and higher (not released at the time of writing) …