FAQ  •  Register  •  Login

Using Beepola with ZX BASIC

<<

LTee

Posts: 153

Joined: Tue Jul 07, 2009 2:54 pm

Post Tue Aug 09, 2011 9:09 am

Using Beepola with ZX BASIC

Using Beepola to add tunes to your ZX BASIC projects is actually pretty easy. Beepola is able to export its players and songs as .TAP files, which you can then merge in with your own code and call from ZX BASIC using standard RANDOMIZE USR calls.

Here's a quick how-to:

1. Make your tune. I can't help much with this bit, but I've successfully managed to integrate the Music Box, Phaser1 and Special FX engines into ZX BASIC, so I surmise they will all work. You can download Beepola from here: http://freestuff.grok.co.uk/beepola/

2. Now you need to compile your tune so that it's useful from ZX BASIC. You do this by selecting 'Compile' from Beepola's 'Tools' menu, which pops up a window with some options. The most important thing here is to make sure you set the player and song to use an area of memory which won't interfere with your own program. I tend to set this high in memory (64000 and up), but bear in mind that each player uses a different amount of memory and you'll also need to leave room for your song data. Each player has a different set of options, but basically it's all up to you here - choose whatever's best for your tune and situation.

3. The easiest way to integrate the song and player is to choose to export from Beepola as a .TAP file. I usually choose the 'code block only' option because you're not going to need the BASIC loader. Once that's saved, you need to load your game AND the player into memory at the same time. It's actually pretty easy to automate all of this using batch files (or their equivalent if you're non-Windows), because .TAP files are remarkably easy to join together. During Dex development, I created a BASIC loader which loaded my game code and the music code and saved that as a .TAP file. Then I used a batch 'make' file like this to build and assemble the game into a single .TAP.

e.g. BASIC LOADER (saved as loader.tap)
  Code:
10 CLEAR 29999: LOAD "" CODE: LOAD "" CODE: RANDOMIZE USR 30000


e.g. BATCH FILE (saved as make.bat)
  Code:
"\program files\zxbasic\zxb.py" dex.bas --output=dexgame.tap --org=30000 -t -Z
copy /b loader.tap + dexgame.tap + DexJingle.tap Dex.tap


The first line of the batch file compiles the game. Once done, the 'copy' command takes the loader, game code and tune and merges them all together into one large .TAP file (called Dex.tap) that I can just double-click and run. Don't forget the /b switch on the copy operation, otherwise the files will be copied as text rather than binary and probably won't work.

4. If your game is to have multiple tunes, you only need to have one copy of the player - you don't need a separate copy of the player for each tune. Each Beepola engine has a couple of POKEable memory addresses near the start of the player code which points to the tune to be played. If you make more than one tune, export those from Beepola as 'song data only' .TAP files. Make sure that you choose the same settings as for your main tune and that you place the song data at a memory location that is away from both your game code AND the first tune's code.

5. During all of these steps, remember to keep track of the memory addresses that you have compiled the music data to. This is rather important as without the addresses you won't know what to call from your game. Including the address in your filenames as a reminder might be a good idea! :)

6. Once you have everything ready to go, all that's left to do is to call the player from within your own ZX BASIC code. This is actually very simple - just a standard RANDOMIZE USR xxxxx call (where xxxxx is the address you compiled the player to) will do the trick. However, if you're making this call from within a ZX BASIC sub or function block, be aware that you need to preserve the IX register or the Spectrum is likely to crash - more details on this below. If you wish to play one of the 'extra' tunes described in point 4, you'll first need to POKE the relevant memory addresses with the location of the new song data - Beepola's documentation will tell you how to calculate what these addresses are for each individual engine.

7. This all sounds a bit complicated, but it really isn't. It's probably easier to show in an example, so I'll show you how I created my music playing subroutine for Dex. See the code fragment below:

  Code:
'some constants
const TUNESON as UBYTE = 1
const TUNEPLAYERADDR as UINTEGER = 64000
const TUNE1 as UINTEGER = 64798
const TUNE2 as UINTEGER = 64850
const TUNE3 as UINTEGER = 64900

const TUNEMAIN as UBYTE = 1
const TUNELEVELSTART as UBYTE = 2
const TUNELEVELEND as UBYTE = 3
const TUNEGAMEOVER as UBYTE = 4

'plays a piece of music
SUB playMusic(tune as UBYTE)
   DIM SongAddr as UINTEGER = 0
   
   'select the correct tune
   if tune = TUNEMAIN then
      SongAddr = TUNE3
   elseif tune = TUNELEVELSTART then
      SongAddr = TUNE1
   elseif tune = TUNELEVELEND then
      SongAddr = TUNE3
   elseif tune = TUNEGAMEOVER then
      SongAddr = TUNE2
   end if
   
   'call the music player
   if TUNESON = 1 and SongAddr > 0 then
      
      'poke the values for the tune start
      poke TUNEPLAYERADDR + 1, SongAddr - 256 * INT(SongAddr / 256)
      poke TUNEPLAYERADDR + 2, INT(SongAddr / 256)
      
      'and play the tune (remember to preserve IX register or it'll crash)
      asm
         push ix
      end asm
      randomize usr TUNEPLAYERADDR
      asm
         pop ix
      end asm
      
   end if
   
END SUB


This routine is basically all of the stuff I described above squashed into a single sub. The main music player was compiled and loaded to 64000, which I've put into a constant. The three tunes I use also have their memory locations described by constants. To play a tune, I call 'playMusic(TUNEMAIN)' (or whatever) and the SUB does all the rest.

You'll see that the address of the tune is determined by the constant I pass - this address is then POKEd into the player engine as described in Beepola's docs. Because we're calling from a SUB, the IX register needs to be preserved - this is easily done with a simple 'push ix' in an ASM block. Once we've done that, it's safe to call the player with 'RANDOMIZE USR'. Once the player returns control to us, we 'pop' the value of IX to allow us to return safely from the subroutine.

Job done!


I hope this is clear, it seems a lot more complicated to write down than it is in my head. If anyone has further questions, please feel free to ask! :)
<<

JBGV

Posts: 65

Joined: Wed Feb 16, 2011 6:12 am

Post Thu Aug 11, 2011 6:19 am

Re: Using Beepola with ZX BASIC

It`s very interesting ¡

I will try to use

Thanks
<<

oblo

Posts: 60

Joined: Tue Jul 12, 2011 5:23 pm

Post Wed Aug 17, 2011 8:44 pm

Re: Using Beepola with ZX BASIC

Hey, great how-to, thanks! :D I've managed to put one song with this method but now that I know that the player can be reused, I can put more that one in a game without loss too much memory.

Only one question, with Beeopola, is not possible export the song to a BEEP Basic list, isn't?

Cheers
<<

LTee

Posts: 153

Joined: Tue Jul 07, 2009 2:54 pm

Post Fri Aug 19, 2011 8:13 am

Re: Using Beepola with ZX BASIC

No, you can't export to a list of BEEPs - Beepola doesn't support making tunes just for the beeper, you can only use one of the provided multi-channel beep engines.
<<

JBGV

Posts: 65

Joined: Wed Feb 16, 2011 6:12 am

Post Fri Aug 19, 2011 10:24 am

Re: Using Beepola with ZX BASIC

There´s a program that transforms "MIDI" to "BEEP":

http://matt.west.co.tt/music/midibeep/


I've tried it and it works well
<<

LTee

Posts: 153

Joined: Tue Jul 07, 2009 2:54 pm

Post Fri Aug 19, 2011 11:12 pm

Re: Using Beepola with ZX BASIC

Heh heh - that's quite impressive! I might play around with that a bit myself!
<<

oblo

Posts: 60

Joined: Tue Jul 12, 2011 5:23 pm

Post Sat Aug 20, 2011 12:05 am

Re: Using Beepola with ZX BASIC

JBGV wrote:There´s a program that transforms "MIDI" to "BEEP":

http://matt.west.co.tt/music/midibeep/


I've tried it and it works well


Wow, thanks a lot! I've tried it and works impressibly well :)

Cheers
<<

JBGV

Posts: 65

Joined: Wed Feb 16, 2011 6:12 am

Post Mon Sep 05, 2011 9:16 pm

Re: Using Beepola with ZX BASIC

Hello ¡

Works perfectly (THANKS !!).


I have a few questions about Beepola:

1) How works the option "Exit after every note (for in-game music)" ?


I want to put the call to sub in the main loop of the game. I only get sound the first note again and again.


2) To make sure set the player and song to use an area of memory which won't interfere with the program, I try to put the asm code beepola generated in the program itself:

(I remove previously the colons at the end of the label before the EQUs http://www.boriel.com/forum/post2183.html?hilit=equ%20beepola#p2183 )



  Code:
(...)

    ASM
    PUSH IX
    END ASM

    RANDOMIZE USR @OLE

    ASM
    POP IX
    END ASM

END SUB






OLE:

ASM

; *****************************************************************************
; * The Music Box Player Engine
; *
; * Based on code written by Mark Alexander for the utility, The Music Box.
; * Modified by Chris Cowley
; *
; * Produced by Beepola v1.06.01
; ******************************************************************************
 
START:
                          LD    HL,MUSICDATA         ;  <- Pointer to Music Data. Change
                                                     ;     this to play a different song
                          LD   A,(HL)                         ; Get the loop start pointer
                          LD   (PATTERN_LOOP_BEGIN),A
                          INC  HL
                          LD   A,(HL)                         ; Get the song end pointer
                          LD   (PATTERN_LOOP_END),A
                          INC  HL

(... etc ...)


This also works well, but can you put more than one song in this way??


THANKS AND REGARDS
<<

LTee

Posts: 153

Joined: Tue Jul 07, 2009 2:54 pm

Post Wed Sep 07, 2011 12:33 pm

Re: Using Beepola with ZX BASIC

1. I've not used that option, so I'm not really sure. I figured you'd just keep calling the routine over and over and it would automatically play the 'next' note, but maybe there's more to it than that?

2. I don't see any reason why not providing you can also find a safe area of memory to load the extra song data. When you export 'extra' songs it doesn't produce any ASM (because there's no player), just a bunch of notes to feed the existing player. You could load those files separately or maybe find a way to turn them into lines of .defb to include them in your source.
<<

JBGV

Posts: 65

Joined: Wed Feb 16, 2011 6:12 am

Post Wed Sep 07, 2011 8:19 pm

Re: Using Beepola with ZX BASIC

Hello, first thank you, Ltee. :D


1. I've not used that option, so I'm not really sure. I figured you'd just keep calling the routine over and over and it would automatically play the 'next' note, but maybe there's more to it than that?

1. I thought that but it always sounds the same note, I'm doing something wrong.

2. I don't see any reason why not providing you can also find a safe area of memory to load the extra song data. When you export 'extra' songs it doesn't produce any ASM (because there's no player), just a bunch of notes to feed the existing player. You could load those files separately or maybe find a way to turn them into lines of .defb to include them in your source.

2. You're right, i can find a safe area of memory to load the extra song data, anyway I will try to include the DEFB in the code, I'm learning ASM and will be a good exercise. :roll:

I'm experimenting with a game for the CSSCGC 2011 :oops:
<<

boriel

Site Admin

Posts: 1462

Joined: Wed Nov 01, 2006 6:18 pm

Location: Santa Cruz de Tenerife, Spain

Post Fri Aug 04, 2017 10:46 am

Re: Using Beepola with ZX BASIC

While reading again this thread, I've realized how much talent is here!! 8)
With the arrival of ZX Next and ZX Uno the retroscene is back and stronger than ever. I wonder were all you are guys! :|

Return to How-To & Tutorials

Who is online

Users browsing this forum: No registered users and 0 guests

cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by Vjacheslav Trushkin for Free Forums/DivisionCore.

phpBB SEO