Anteckningar från Regnbågslandet

Bakgrund

ZX Spectrum var en inspirationskälla för en hel generation barn. Vi knappade in små BASIC-program på de mjuka gummitangenterna och lärde oss att programmera. Med en Spectrumemulator, som fuse, går det att emulera sin barndom. Det går även att skriva helt ny kod, och det är precis vad jag gjorde under semestern 😀

ZX Beep

Checka ut koden och skriv make. Då skapas (om allt går bra) filen beep.tap, som kan laddas in i en emulator där den spelar upp en liten melodi på Spectrumens beeper.

Mer intressant är kanske att ZX Beep Kan användas som skelett för dina egna assemblerprogram till ZX Spectrum. Läs vidare om du är intresserad av mina spridda minnesanteckningar under tiden jag skrev ZX Beep.

Minne

;; Spectrum 48k
;; Memory Map
0000-3FFF  ; ROM (BASIC)
4000-7FFF  ; RAM (Work RAM + VRAM)
8000-FFFF  ; Additional RAM

Spectrum 16k: saknar 8000-FFFF.

ROM är hårdkodat för BASIC och går inte att skriva till. Men det går att anropa rutiner i ROM från sina egna program. På följande adress finns hela ROM disassemblerat med kommentarer från olika personer som genom åren försökt lista ut vad allting betyder:

ROM → http://www.wearmouth.demon.co.uk/zx82.htm ← ROM

RAM-adresserna 4000-7FFF, som finns för bägge modellerna av Spectrum, delas in i följande areor:

4000-7F57  ; RAMTOP
7F58-7FFF  ; UDG - P-RAMT

Arean mellan 4000 och RAMTOP används som arbetsminne av BASIC-systemet medan området mellan UDG (User Defined Graphics) och P-RAMT används för grafik (fonter). Spectrum 48k har RAMTOP FF57 och P-RAMT FFFF (byt ut första 7:an mot F bara). Av den första arean används för övrigt adress 4000-5AFF som grafikminne (1-bits pixel data ”displayfilen” + färgattribut för 8×8 pixel-celler ”attributfilen”).

Frågan är nu var vi kan lägga våra egna program. Minnet för BASIC-program sköts automatiskt medan assemblerprogram måste hantera minnet manuellt.

Tricket är att sänka RAMTOP och lägga den egna koden i utrymmet som uppstår mellan den nya, lägre RAMTOP och UDG. Följande BASIC-kommando sänker RAMTOP till 7D00-1:

CLEAR 31999

Nu finns 600 bytes lediga mellan 32000 (7D00) och 32600 (7F58, UDG). Det låter lite, men 600 bytes räcker bra för att experimentera med assemblerkod till Spectrum. Tar det ändå slut, sänk RAMTOP så lågt du behöver och vågar (teoretiskt är det lägsta som går 5CCA). Det var alltså långt ifrån 16k som gick att använda till sina egna program på Spectrum 16k…

På Spectrum 48k är det enklast att sätta RAMTOP till 32767 (7FFF):

randomizeDå frigörs 16k additional RAM (varav allt, utom lite UDG på slutet, kan användas av egna program). Tar det ändå slut går det alltid att sänka RAMTOP lite till, som för Spectrum 16k.

BASIC har som sagt mycket färdigt i ROM. Dessa rutiner kan anropas som subrutiner från dina egna assemblerprogram för att spara plats. Ja, det går även att anropa dem från BASIC med funktionen USR. För att hoppa till en subrutin i minnet och skriva ut returvärdet på skärmen, kör:

PRINT USR <decimal adress>

Se disassembleringen av ROM för att se vilka rutiner som finns och vilka adresser de har. För att bara köra rutinen utan att skriva ut returvärdet kan någon ”tyst” BASIC-funktion användas, som RANDOMIZE:

RANDOMIZE USR 32768

Ovanstående rad hoppar till adress 32768 och kör tills den stöter på instruktionen ret, som får programmet att hoppa tillbaka till BASIC. Nu fattas bara lite kod att lägga på adress 32768. Ett sätt är att mata in maskinkoden manuellt i minnet från BASIC, med funktionen POKE. Det är dock enklare att skriva assemblerkod på en PC och låta en assembler översätta till maskinkod (se hur ZX Beep gör).

Emulator

För att enkelt ladda in koden till en emulator kan t.ex. formatet TAP användas (står för tape, mjukvara lagrades tidigare på kasettband). Ett annat populärt format är TZX. De flesta assemblers skickar dock inte ut någon sådan fil, utan en binär BIN-fil med rå maskinkod. Som tur är finns en utility som översätter från BIN → TAP (och samtidigt skapar ett litet BASIC-program som sänker RAMTOP, laddar koden till adress 32768 och kör igång den med USR; kallas loader).

Men först behövs en assembler för Spectrums CPU (Z80) . ZX Beep använder z80asm, den är liten, kvick och funkar bra.

bortombasic

Så måste det finnas något att kompilera. Testa t.ex. att assemblera följande program, som anropar funktionen BEEPER i ROM (adress 03B5) för att beepa ett C (261.626 Hz) i en sekund:

org     32768
ld      hl, $066b
ld      de, $0106
call    $03b5     ; BEEPER i ROM
ret

Se kommentarer ovanför L03B5 för info om hur värdena som stoppas in i HL och DE beräknas.

Om du lyckas kompilera programmet, bygga en TAP-fil och ladda in den i en emulator (t.ex. fuse) har du kommit en bra bit på vägen. Sen är det bara att bygga vidare. Kanske göra lite chiptunes 🙂

Tangentbord

Spectrum Keymap
På de flesta emulatorer mappas CAPS SHIFT till Shift och SYMBOL SHIFT till Ctrl, Alt eller Meta (cmd, win, ”diamant” eller liknande). Utan shift skrivs de vita nyckelorden ut vid K-prompt. Med SYMBOL SHIFT skrivs de röda nyckelorden på tangenterna ut. Genom att trycka SYMBOL SHIFT + CAPS SHIFT ändras prompten till E. Nu skrivs de gröna nyckelorden utan shift och de röda nyckelorden under tangenterna ut med SYMBOL SHIFT. Vid L-prompt skrivs bokstäver och siffror ut precis som på en vanlig PC. Ett effektivt utnyttjande av bara 40 tangenter.

Exempel. För att skriva PRINT ”Albert”, tryck först P (i K-mod) som ger nyckelordet PRINT. Samtidigt ändras prompten till L (står för Letters). SYMBOL SHIFT + P ger tecknet . Mata sen in texten Albert (CAPS SHIFT ger stora bokstäver i L-prompt) och ett avslutande . ENTER.

Det kan vara smidigt att ha en bild av tangentbordet att titta på för att skriva BASIC under en emulator. För att bara köra TAP-filer räcker det dock att klicka med musen. Jag har ordnat så att TAP-filen automatiskt körs igång under fuse när jag klickar på en TAP-fil i filhanteraren.

Happy Hacking! ////

Referenser

Advertisements

Om albertveli

Grävande programmerare.
Det här inlägget postades i Nostalgi, Programmering. Bokmärk permalänken.

Kommentera

Fyll i dina uppgifter nedan eller klicka på en ikon för att logga in:

WordPress.com Logo

Du kommenterar med ditt WordPress.com-konto. Logga ut / Ändra )

Twitter-bild

Du kommenterar med ditt Twitter-konto. Logga ut / Ändra )

Facebook-foto

Du kommenterar med ditt Facebook-konto. Logga ut / Ändra )

Google+ photo

Du kommenterar med ditt Google+-konto. Logga ut / Ändra )

Ansluter till %s