-
Notifications
You must be signed in to change notification settings - Fork 0
Beep the ZX Spectrum
License
AlbertVeli/ZX_Beep
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
______ __ __ ______ ______ ______ ______ /\___ \ /\_\_\_\ /\ == \ /\ ___\ /\ ___\ /\ == \ \/_/ /__ \/_/\_\/_ \ \ __< \ \ __\ \ \ __\ \ \ _-/ /\_____\ /\_\/\_\ \ \_____\ \ \_____\ \ \_____\ \ \_\ \/_____/ \/_/\/_/ \/_____/ \/_____/ \/_____/ \/_/ "What is a Computer Good For? Your new Timex Sinclair 2000 computer is a very special instrument. It is a tool that can increase the power of your mind as a hammer or a wheelbarrow assists your muscles." --TS2068 User Manual The purpose of this repository is primarily to be a skeleton you can base your own ZX Spectrum projects upon. It compiles assembly code and outputs a TAP-file, which can be read by most Spectrum emulators. I use fuse. http://fuse-emulator.sourceforge.net/ BACKGROUND When I was young the ZX Spectrum was a great inspiration. Me and my friends entered BASIC-programs from computer magazines and manuals on those soft rubber-keys. Even though we didn't realize it at the time, we had embarked upon a path of learning the art (or should I call it science?) of computer software programming. Today we can emulate that childhood with tools like fuse, and even write new code for it. BUT WHAT DOES IT DO? ZX Beep repeatedly calls the BEEPER subroutine in the Spectrum ROM to play some sweeping sound effects and an example song called Mandom Mod. A marching tune written a long time ago in a place far, far away (Orsa/Dalarna), long before the age of impeding copyright claims. http://albertveli.github.io/ZX_Beep/img/mandom_mod.png BUILD You need a git client, make and a C-compiler. On Debian-based systems these can be found in the packages git, make and gcc: apt-get install git make gcc See http://help.github.com/articles/set-up-git for info on installing git on various systems. I have successfully compiled the code on Gentoo, Debian and OS X Mountain Lion. OS X had make and gcc installed by default, so I only had to install git. On Windows it is possible to compile it using Msys+MinGW+Git, see mingw_install.rtf. Ok, lets go. Fetch the ZX Beep source code from github: git clone https://github.com/AlbertVeli/ZX_Beep.git And build it with make: make If everything works out, beep.tap should be created. MODIFY To create your own TAP-file, edit the first lines in the Makefile (SRC and INCSRCS), and replace with your own .asm file(s). If you want to use it as-is and only create a new song, copy mandom_mod.asm to a new file with the name of your song and change the notes data. Then replace the string "mandom_mod.asm" in Makefile / beep.asm. If you change some of the mandom_mod labels in the song file, remember to do the corresponding changes in beep.asm. You may also want to remove the line 'include "sweep.asm"' and the calls to sweep_octave from beep.asm to save some precious space. To save even more space it is possible to remove entire octaves from octaves.asm (but only at the beginning and at the end). You can for instance remove the A1, A6 and A7 octaves if they are not used. SONG DATA Structure: Each note consist of a Pitch,Length pair in the range 0-255 (one byte). Pitch = number of semitones above the first note. If A2 (A number 2 on piano) is the base octave, the pitch values becomes: 0 A2, 1 Bb, 2 B, 3 C, 4 C#, 5 D, 6 Eb, 7 E, 8 F, 9 F#, 10 G, 11 G# 12 A3, 13 Bb, 14 B, 15 C, 16 C#, 17 D, 18 Eb, 19 E, 20 F, 21 F#, 22 G, 23 G# 24 A4, 25 Bb, 26 B, 27 C, 28 C#, 29 D, 30 Eb, 31 E, 32 F, 33 F#, 34 G, 35 G# etc Length = Duration of note: 1 -> Whole note (1 s) 2 -> Half note (1/2 s) 3 -> Quarter note (1/4 s) 4 -> Eigth note (1/8 s) 5 -> Sixteenth note (1/16 s) 6 -> Thirty-second note (1/32 s) etc Example. 19,4 -> E3, Eigth note. FREQUENCIES In the song data frequencies are given as semitones above the base note. But the BEEPER subroutine in ROM neither takes frequencies in Hz, nor in semitones. Instead the frequency data word is calculated in a rather intricate manner. See comments just before L03B5 in the ROM disassembly: http://www.wearmouth.demon.co.uk/zx82.htm#L03B5 The algorithm given in the disassembly translates from frequency (Hz) to register values. But we also need to calculate what frequency to use somehow. It turns out there are many ways to calculate tone frequencies. The standard way is to use 440 Hz for the fourth A on a piano (A4) and calculate the rest of the frequencies relative 440 Hz with the alorithm EQUAL TEMPERAMENT. With this algorithm the frequency for a note n semitones away from A4 becomes: Freq(n) = 440 * 2^(n/12) This works for all keys (because the errors are evenly distributed). But if you want to fine tune harmonies for a specific key, Hermann von Helmholtz (in the book "Sensations of Tone", published 1863) figured out more optimal frequencies. The following ratios (relative the base note frequency) can be used to calculate the 12 notes in an octave: 1 / 1 ; 0 Unison 25 / 24 ; 1 Minor Second 9 / 8 ; 2 Major Second 6 / 5 ; 3 Minor Third 5 / 4 ; 4 Major Third 4 / 3 ; 5 Fourth 45 / 32 ; 6 Diminished Fifth 3 / 2 ; 7 Fifth 8 / 5 ; 8 Minor Sixth 5 / 3 ; 9 Major Sixth 9 / 5 ; 10 Minor Seventh 15 / 8 ; 11 Major Seventh This is called the JUST scale (aka Harmonic or Helmholtz). Helmholtz based his work on older philosophical writings attributed to people like Pythagoras, Andreas Werckmeister et al. The essence is: lower numbers in the ratio -> better harmony. Example. A4 = 440 Hz, C (minor third relative A, 3 semitones up) becomes: JUST ; 440 * (6/5) = 528 Hz EQ.TEMPERED ; 440 * 2^(3/12) = 523.25 Hz The difference can easily be heard by the naked ear. Try playing two tones, 440 and 528 Hz together. Then compare to 440 / 523.25 Hz. The first tone-pair gives cleaner harmony (it is also possible to visualize this difference using Lissajous curves). The downside of JUST scale is that frequencies has to be re-calculated to play a song in a different key. EQUAL TEMPERAMENT is a compromise tuning that works equally well (or bad) for all keys. These frequency calculations are performed by freqs.c and output to octaves.asm. The pre-calculated lookup-tables in octaves.asm are then used by the beeper routine in beep.asm. To change scale, compile freqs.c by running "make freqs" and generate the frequencies of your choice. Example. Seven octaves in JUST scale, starting at C = 256 Hz (makes all C:s powers of two and the other notes low-integer ratios in relation to powers of two) run: ./freqs -o 7 -j 256 And to generate six octaves with the vanilla EQUAL TEMPERED scale, starting at 110 Hz (A, two octaves below 440 Hz), run: ./freqs -o 6 110 Paste the output into octaves.asm and build a new TAP. EXTERNAL CODE USED - z80asm ; http://www.nongnu.org/z80asm/ Z80asm is included as a git submodule. The submodule will be fetched the first time you run make. REFERENCES - The BASIC manual for ZX Spectrum is exceptionally well written. Start there. http://www.worldofspectrum.org/ZXBasicManual/index.html - World of Spectrum has links tho all things Spectrum http://www.worldofspectrum.org/ - Introduction to Z80 Assembler http://www.worldofspectrum.org/Z80.html - Z80 Heaven has details for the complete Z80 instruction set http://z80-heaven.wikidot.com/instructions-set - Details of what happens in each Z80 instruction Machine Cycle* http://www.z80.info/z80ins.txt Happy Hacking! /Albert * Each Machine Cycle takes 3-6 T-cycles (real CPU clock cycles). Spectrum runs the Z80 at 3.5 MHz. Example. If an instruction takes 9 T-cycles it will execute in 9/3500000 seconds = 2.57 microseconds. Z80 was pretty deterministic. Modern CPU:s are more unreliable when it comes to timing (caches, pipelining etc complicate matters).
About
Beep the ZX Spectrum
Resources
License
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published