Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Small snippet to make the AY scream a bit
#1
I ported some old code I developed with the aid of a couple of snippets published in Microhobby and some documentation for the AY chip to ZX Basic. The original was plain interpreted Sinclair BASIC. It may be useful to create simple sound effects, but nothing very fancy. Porting WYZ's replayer would be a better idea, but I have no time at the moment.

Try this:

Code:
Dim sonidos (4, 13) As Byte => {_
    {100,50,0,0,0,0,4,216,31,0,0,10,10,0}, _
    {250,250,0,0,0,0,15,248,31,0,0,10,10,0}, _
    {10,10,0,0,0,0,29,216,31,0,0,4,4,0}, _
    {10,100,0,0,0,0,15,248,31,0,0,50,50,0}, _
    {15,1,0,0,0,0,15,248,31,0,0,50,50,0} _
}
Dim n As Byte

Cls
For n = 0 To 4                          ' We'll play 4 sounds
    Print "SFX #"; n                    ' Print which one
    ayPlaySound (n)                     ' Play sound # i
    Pause 100                           ' Wait for 2 secs.
Next n

Sub ayPlaySound (sonido As Byte)
    ' This SUB plays the sound passed as parameter
    ' Sounds are taken from table "sonidos", which
    ' must be defined globally.

    Dim i As Byte
  
    For i = 0 To 13
        Out 65533, i                    ' Select which AY register
        Out 49149, sonidos (sonido, i)  ' Write a value in it
    Next i
End Sub

The values in the array are pretty straightforward. The first 14 AY registers are written by the routine, just look at this table and you may create your own wacky sounds.

Code:
AY REGISTERS

00              Channel A fine pitch            8-bit (0-255)
01              Channel A course pitch          4-bit (0-15)
02              Channel B fine pitch            8-bit (0-255)
03              Channel B course pitch          4-bit (0-15)
04              Channel C fine pitch            8-bit (0-255)
05              Channel C course pitch          4-bit (0-15)
06              Noise pitch                     5-bit (0-31)
07              Mixer                           8-bit (see below)
08              Channel A volume                4-bit (0-15, see below)
09              Channel B volume                4-bit (0-15, see below)
10              Channel C volume                4-bit (0-15, see below)
11              Envelope fine duration          8-bit (0-255)
12              Envelope course duration        8-bit (0-255)
13              Envelope shape                  4-bit (0-15)
14              I/O port A                      8-bit (0-255)
15              I/O port B                      8-bit (0-255)

Bit:
7       6        5        4        3        2        1        0
_         _
I/O     I/O     Noise    Noise    Noise     Tone     Tone     Tone
B        A        C        B        A        C        B        A
Reply
#2
na_th_an Wrote:I ported some old code I developed with the aid of a couple of snippets published in Microhobby and some documentation for the AY chip to ZX Basic. The original was plain interpreted Sinclair BASIC. It may be useful to create simple sound effects, but nothing very fancy. Porting WYZ's replayer would be a better idea, but I have no time at the moment.
This is *very* interesting. If you finally get to find out how to do it, we could have a play.bas library or similar. I've read you know about the trackers. It would be nice to use IM2 + trackers with ZX Basic too. :-)

Thanks for sharing.
Reply
#3
We have used WYZ's player (and Augusto Ruiz's tracker to create suitable music for it) if all our releases for the 128K Spectrum and the Amstrad CPC. Porting it should be easy provided a way to activate IM2 and set up a simple ISR which calls the play routine exists. Using z88dk and splib2 this is pretty straightforward as splib2 includes a great IM2 ISR framework. You just need a routine which makes a call to the play routine and hook it to the ISR list.

Anyways, before doing anything, I think WYZ should be contacted. He always gives his player and sources to anyone who requests it to create a game (right now it's been used to create MSX, CPC and ZX Spectrum games - Artaburu's CPCRSLIB for z88dk has the player included as an integrated module), but I'm not quite sure that his code is "open source" so I can't distribute it freely.

Check, for example, Uwol. The music (created by Augusto himself using his tracker) is played using WYZ's player.

<!-- m --><a class="postlink" href="http://www.mojontwins.com/juegos_mojonos/uwol-quest-for-money/">http://www.mojontwins.com/juegos_mojono ... for-money/</a><!-- m -->
Reply
#4
Very nicely done, Na_th_an. That's half the game for a 128!

I was thinking that I could force page swapping on a 128, by coding a routine to do it manually. Then I realized I'd have to call code in other pages by inference, and that would be a pain.

I did wonder if I could get the compiler to do

[code]
org 49152
[code for one page]
org 49152
[code for next page]
org 49152
[code for next page]

And so on. Yes, it would overwrite itself - but the location references for calls would be correct in the generated code.

On the whole though, I've found the results of using ORG in the code to be rather unfortunate Sad


Then of course, compile each page as an item separately, and save out 16K blocks of code, and then load them in, and page flip to load each successive one. Voila. Data in multiple pages...

it's a crazy plan, but it might just work :-)

I've shown that one can manually push the compiler to set up an ISR Mode 2 routine! Remember this? : <!-- m --><a class="postlink" href="http://britlion.googlepages.com/Sprity.z80">http://britlion.googlepages.com/Sprity.z80</a><!-- m -->
Reply
#5
britlion Wrote:Very nicely done, Na_th_an. That's half the game for a 128!

I was thinking that I could force page swapping on a 128, by coding a routine to do it manually. Then I realized I'd have to call code in other pages by inference, and that would be a pain.

I did wonder if I could get the compiler to do

Code:
org 49152
[code for one page]
org 49152
[code for next page]
org 49152
[code for next page]

And so on. Yes, it would overwrite it - but the location references for calls would be correct in the generated code.

Then of course, compile each page as an item separately, and save out 16K blocks of code, and then load them in, and page flip to load each successive one. Voila. Data in multiple pages...

it's a crazy plan, but it might just work :-)

I've shown that one can manually push the compiler to set up an ISR Mode 2 routine! Remember this? : <!-- m --><a class="postlink" href="http://britlion.googlepages.com/Sprity.z80">http://britlion.googlepages.com/Sprity.z80</a><!-- m -->

I was thinking in something like
Code:
FUNCTION/SUB xxxx AT @label / <number address>
...
END FUNCTION / SUB
the problem with this is some functions might overlap. Most compilers I know aren't able to do that. Also keep in mind that, regardless its name, ZX BASIC aims to be a generic compiler (not only Speccy, but Z80 in the middle term, and architecture generic in the long term). This feature is very Speccy 128K specific and putting things like that in the ZX BASIC syntax might break the compiler on other architectures.

I think it's better to do as suggested: move those things to the low-level asm blocks.

Having said that, the idea of FUNCTION ... INTERRUPT is very common, and it will be implemented.
Reply
#6
Which other architectures are you considering, Boriel?

Would having something like a PAGE # assembler directive work - that makes references to this block as though it was in the top 16k of memory, but makes a separate code block in the flie? I assume a zx basic program and .tap file is sorta zx spectrum specific as it is, so there's precedent...
Reply
#7
britlion Wrote:Which other architectures are you considering, Boriel?

Would having something like a PAGE # assembler directive work - that makes references to this block as though it was in the top 16k of memory, but makes a separate code block in the file? I assume a zx basic program and .tap file is sorta zx spectrum specific as it is, so there's precedent...
Wel, some ideas:
  • Z80 architectures: MSX, Amstrad, ZX Spectrum clones, Gameboy, etc...
  • 68000 architectures: QL (many people asking for it)
  • .NET To run your programs in .NET (this should be easy)
  • JAVA -> Your program embedded in a browser
  • Javascript -> Like JAVA but easier. I'm seriously thinking it working on these now...
  • C -> Port your program to C so you could recompile it on your arch with less pain. Should be easy using ALLEGRO / SDL. Seriously thinking on starting it...
  • Commodore 64 (may people asking for it)
I was even considering PS3 (yes, I own a FAT PS3 model). But since Sony removed the "Other OS" option, I stopped.

I tried hard to keep Sinclair BASIC compatibility whilst expanding the language. So people wanting to port their old Speccy BASIC programs should find it easier that starting their programs from scratch. But definitely, people make new programs should use the FreeBasic-like (not 100%) syntax (Functions, subs, etc...).

Problems: Some functions might definitely not be portable. E.g. ATTR (which color value to return on 16x16 different color set?), SCREEN$, POINT etc. These functions are external Wink ones. That's why you have to use --sinclair or #include to use them. External functions and subs need parenthesis since they are just normal .BAS files (Visual Basic allows calling SUBS with no parenthesis but I think this will clutter the language syntax and the parser). So, to maintain syntax compatibility with Speccy BASIC, some inner subs like RND(), PLOT(), DRAW(), INKEY$(), etc... has been integrated in the BASIC syntax as inner (integrated with the compiler syntax) functions and subs.

Those INNER (not external) functions, like DRAW, PLOT or BEEP might *not* be portable. A clear example are VAL and INPUT. INPUT sub is not compatible with compiled ZX BASIC because It's impossible to call the ROM routine which needs INTERPRETED Basic. I could implement it from scratch (as done with PRINT), but then a simple PRINT / INPUT will take a lot of memory. Hence, an INPUT() routine very like FreeBasic was implemented.

So porting basically is planned like this:
  1. Create a directory ports/ in the compiler structure
  2. Create a subdirectory for each architecture within ports/ directory e.g. ports/spectrum48k (yes, spectrum128k could be a different architecture)
  3. For each architecture port dir, there must be a library-asm and library/ directory. There could be a generic library/ for all architectures provided they don't use ASM...END ASM
  4. For each architecture, the backend/ compiler directory must be copied in ports/<arch>/backend and re-implemented for each architecture.
  5. Invoking the compiler with --arch=<arch> will check if /ports/<arch> exists and exit with an "Arch. not supported" error if not.

Obviously, I can't do all the above alone. I'm still planning things in the compiler before releasing a ZX BASIC Backend SDK to develop ports.

BTW: to save memory, a --use-internal-print flag will be implemented soon (replacing my print routine with the standard ROM one, but disabling BOLD, ITALIC and OVER 2/3 features).
Reply
#8
Well, most of the time you don't need that much code so you need to split it accross pages. In all our games, 128K RAM management is done manually, as all the code fits in low RAM, and some less used parts reside in RAM0 ($C000 onwards). Other RAM pages are filled with data: music, the music player, map data, graphics, static screens... When you need something, you page in the correct page, get what you need, and then set RAM0 back before continuing.

In fact, our ISR is prepared to page in RAM1, execute the music player callback routine, page in RAM0, and exit.
Reply
#9
boriel Wrote:Wel, some ideas:
  • Z80 architectures: MSX, Amstrad, ZX Spectrum clones, Gameboy, etc...
  • 68000 architectures: QL (many people asking for it)
  • .NET To run your programs in .NET (this should be easy)
  • JAVA -> Your program embedded in a browser
  • Javascript -> Like JAVA but easier. I'm seriously thinking it working on these now...
  • C -> Port your program to C so you could recompile it on your arch with less pain. Should be easy using ALLEGRO / SDL. Seriously thinking on starting it...
  • Commodore 64 (may people asking for it)
I was even considering PS3 (yes, I own a FAT PS3 model). But since Sony removed the "Other OS" option, I stopped.
I own a Commodore C64 too. Maybe not a bad idea to maka a Compiler, as there does not exist a crosscompiler yet. And Atari XL/XE has a similar architecture too. But for the start Spectrum Compiler is fine! Maybe you can add SAM Coupé support too?

boriel Wrote:I tried hard to keep Sinclair BASIC compatibility whilst expanding the language. So people wanting to port their old Speccy BASIC programs should find it easier that starting their programs from scratch. But definitely, people make new programs should use the FreeBasic-like (not 100%) syntax (Functions, subs, etc...).
I do so and even not use line numbers. Thank you for making programming on Spectrum more modern.

boriel Wrote:Problems: Some functions might definitely not be portable. E.g. ATTR (which color value to return on 16x16 different color set?), SCREEN$, POINT etc. These functions are external Wink ones. That's why you have to use --sinclair or #include to use them. External functions and subs need parenthesis since they are just normal .BAS files (Visual Basic allows calling SUBS with no parenthesis but I think this will clutter the language syntax and the parser). So, to maintain syntax compatibility with Speccy BASIC, some inner subs like RND(), PLOT(), DRAW(), INKEY$(), etc... has been integrated in the BASIC syntax as inner (integrated with the compiler syntax) functions and subs.
I prefer parenthisis for functions too, and I ***HATE*** VisualBasic. FreeBasic and PureBasic are much better.

boriel Wrote:BTW: to save memory, a --use-internal-print flag will be implemented soon (replacing my print routine with the standard ROM one, but disabling BOLD, ITALIC and OVER 2/3 features).
I like the idea. Looking forward for the next version.
------------------------------------------------------------
http://lcd-one.da.ru redirector is dead
Visit my http://members.inode.at/838331/index.html home page!
Reply
#10
LCD Wrote:
boriel Wrote:Wel, some ideas:
  • Z80 architectures: MSX, Amstrad, ZX Spectrum clones, Gameboy, etc...
  • 68000 architectures: QL (many people asking for it)

Maybe you can add SAM Coupé support too?

I was about to ask for it too. I think SAM Coupé is probably the best designed 8-bit computer. It's a kind of super Spectrum with very advanced features.

I love QL too. I programmed a lot for it years ago. But QL's SuperBasic and its successor SBASIC are very good, and there are some toolkits and compilers for them, so I think the need for a QL cross compiler is less obvious.
Reply
#11
boriel Wrote:BTW: to save memory, a --use-internal-print flag will be implemented soon (replacing my print routine with the standard ROM one, but disabling BOLD, ITALIC and OVER 2/3 features).

And just like that I find out about a feature of the compiler I didn't know about. *facepalm* I had no idea there was an AND/OR version of OVER.

*EDITS THE WIKI* There. Now it's documented. I was talking about the compiler over on WOS, and the main complaint was lack of documentation. You've put lots of clever things like this in, that we only seem to find out by accident!
Reply
#12
britlion Wrote:And just like that I find out about a feature of the compiler I didn't know about. *facepalm* I had no idea there was an AND/OR version of OVER.

*EDITS THE WIKI* There. Now it's documented. I was talking about the compiler over on WOS, and the main complaint was lack of documentation. You've put lots of clever things like this in, that we only seem to find out by accident!

I feel exactly the same! The lack of ZX Basic documentation is the main reason I'm seriously considering the use of the good old Beta Basic 4.0 to write my current project... Beta Basic has excellent manuals where everything is explained with full detail and lot of examples.

It's a pleasure to code in ZX Basic, with a modern editor, but many times it's very frustating: I feel I'm blind and lost, trying to find out many issues by trial and error, besides the most simple and evident features.

I can contribute to the ZX Basic documentation, but I cannot write down the hidden features or commands nobody knows Wink

I suggest to stop coding for a while and seriously arrange, tidy, complete and update the documentation. That would make it much easier to use ZX Basic: many people would be encouraged to try it, and that would lead to faster debugging and development. Then the documentation should be updated for every single change in the code (command line options, syntax, commands...)

Without a complete and updated documentation, only the Spectrum "zealots" like me Smile dare to try ZX Basic.
Reply
#13
Okay, I will stop development for a while Sad I don't like the current Wiki and I'm seriously considering to move into another one.

So lets freeze compiler development and start documenting it. Lack of documentation is very common on open source projects at the beginning. So be patient. Meanwhile, you can ask for help here in this section (HOW-TO & Tutorials).

I was also considering in writing a free manual (ala ZX Spectrum manual), and put it online. But don't even know which tool (Latex, Word, etc...) to use for writing it.
Reply
#14
boriel Wrote:Okay, I will stop development for a while Sad

It's a hard decision, but at the end the development will benefit a lot of it, because many new people will be able to use ZX Basic and contribute with bugs and suggestions and code.

boriel Wrote:I don't like the current Wiki and I'm seriously considering to move into another one.

I've tried many wikis, but at the end I wrote my own Smile because none of them was perfectly suited to my needs. I would suggest a wiki with standard WikiCreole syntax, but it's not such an important issue; the easy to configure and template the site are more important. I think MediaWiki is too complex to configure and template and customize (but maybe it's only a wrong impression of mine, because I'm not used to it).

boriel Wrote:Lack of documentation is very common on open source projects at the beginning. So be patient.

Yes. I've seen this before in open source solo projects: The developer has the whole program in his mind and doesn't cease to fix and improve it; he has no need and almost no time to document it --it's funnier to code than to write the manual, I know! Smile. So the program grows quickly and the few docs avalaible become obsolete...

When the documentation is well structured, the tool (the wiki, in this case) is friendly and the edit criteria are clear, it's easy for the users (with the developer's supervision) to keep the contents updated. But we (and mainly the developer) have to build the foundations first!

boriel Wrote:I was also considering in writing a free manual (ala ZX Spectrum manual), and put it online.

Such a manual would be very useful, but I think it can wait. Anyway, it could be created more or less automatically with the wiki sources. It's better to have only one documentation reference in the beginning, to save efforts and avoid out of sync.

I suggest to open a new "Documentation" sub-forum to discuss all this and also to announce the achivements about the documentation.
Reply
#15
programandala.net Wrote:[
I suggest to open a new "Documentation" sub-forum to discuss all this and also to announce the achivements about the documentation.
Good idea :!:

Forgot to mention there's a Spanish introductory manual I wrote for an online Magazine last year: ZX Basic: Un sueño hecho realidad (ZX Basic: A dream come true).
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)