Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
128K SPECTRUM COMPATIBILITY...
#1
Forgive me if Iv missed something here, but is your ZX compiler 48k compatible only?....

I would very much like to use your wonderful tool to compile some programs that make use of the PLAY command from 128k Basic...

I don't see any referrence to the PLAY command in any of the online documentation... I was wondering whether this might be a feature that you'd be interestd in adding in the future?...

Since this IS a wishlist, might I also suggest adding the ability to use the PLAY command in the background, using some sort of interrupt driven sound routine?...

Will this project later include 128k BASIC instructions (eg: load!, cat!, for silicon disk, PLAY for sound, etc), or was it always meant to be 48k BASIC only that is represented?...
Reply
#2
How about using some Soundtracker editors and write a own Interrupt routine to call the player? You will be also able to put the music in a different memory bank.
PLAY was never the first choice for music making.
On the other side it would be nice to have interrupt handling ready for use in ZXB:
InterruptsOn @Label or InterruptsOn ?Procedure
InterruptsOff
------------------------------------------------------------
http://lcd-one.da.ru redirector is dead
Visit my http://members.inode.at/838331/index.html home page!
Reply
#3
128K support (PLAY, for example) is planned. I own a +2 my self Wink
The problem is the lack of information about interrupts and play (AY chip) routines. Sad

If I knew where to start...

Also Interrupts are also planed. Something like:
Code:
sub XXX interrupt
...
end sub
or
Code:
sub __INTERRUPT__ xxx
...
end sub
But this have to be implemented carefully. For example, an interrupt will "chain" the previous interrupt (by default, the +48 Timer counter and KeyB reader).

These are just ideas... Smile
Reply
#4
So no initialisation is needed for interrupts? What if the user want to switch them off again?
------------------------------------------------------------
http://lcd-one.da.ru redirector is dead
Visit my http://members.inode.at/838331/index.html home page!
Reply
#5
Interrupts are enabled by default. And are reenabled after every BEEP, SAVE, LOAD & VERIFY since the ZX Spectrum ROM is used for these commands, and these routines reenable the interrupt upon return.

You can disable/enable interrupts with this macro:
Code:
#define EnableInt asm \
            ei \
            end asm \

#define DisableInt asm \
            di \
            end asm

REM Now disable interrupts
DisableInt
...
REM Now enable interrupts
EnableInt

Hope this clarifies it a little.

BTW: I've just incorporated a new FORUM Template (Dark/Speccy like). If you don't like the new forum theme, you can switch back to the original one in your User Preferences Panel.
Reply
#6
But doing so, will it not disable the keyboard scan routine too?
------------------------------------------------------------
http://lcd-one.da.ru redirector is dead
Visit my http://members.inode.at/838331/index.html home page!
Reply
#7
LCD Wrote:But doing so, will it not disable the keyboard scan routine too?
According to my tests, it will stop the FRAMES (PEEK 23672) counting, and key scan is disabled for ROM editor. But you don't usually call the ROM editor (e.g. the INPUT sentence is implemented as a function).

The INKEY$ function works, ok Wink and the interrupts are enabled upon returning to BASIC, so it is safe to use this trick. Just remeber that using BEEP, PAUSE, LOAD, SAVE and VERIFY will reenable interrupts.
Reply
#8
Thank you for the information. If seed is not changing, it will be impossible to change RANDOMIZE "randomly", so it is not "clean". Maybe I can find the way in my old records, where to set the I Register back to call the ROM, to make a clean Interrupt off swiching. Or was it setting back to IM1? I'm not at home here at moment (visiting JHCon party), so I cannot review my records now.
Anyway, it is great that compiled programs will run in DI mode anyway. I was not expecting this.
------------------------------------------------------------
http://lcd-one.da.ru redirector is dead
Visit my http://members.inode.at/838331/index.html home page!
Reply
#9
LCD Wrote:Thank you for the information. If seed is not changing, it will be impossible to change RANDOMIZE "randomly", so it is not "clean". Maybe I can find the way in my old records, where to set the I Register back to call the ROM, to make a clean Interrupt off swiching. Or was it setting back to IM1? I'm not at home here at moment (visiting JHCon party), so I cannot review my records now.
Anyway, it is great that compiled programs will run in DI mode anyway. I was not expecting this.

If you need FRAMES to update then you must use EI and not disable interrupts. But most of the time you needn't FRAMES, anyway. Changing the frames counter will always require EI (using interrupts). I don't understand exactly what where you trying... :?: :?: :?:
Reply
#10
boriel Wrote:If you need FRAMES to update then you must use EI and not disable interrupts. But most of the time you needn't FRAMES, anyway. Changing the frames counter will always require EI (using interrupts). I don't understand exactly what where you trying... :?: :?: :?:
I want to play music in interrupts (in a different memory bank), switch to other song, and switch the music off. I also want to keep the FRAMES counter to re-RANDOMIZE events on the fly and keep the track how long ago the last event occured.
The easiest way at the moment seems to change the CALL in the Interrupt-Routine to a adrees contains RET (201).
------------------------------------------------------------
http://lcd-one.da.ru redirector is dead
Visit my http://members.inode.at/838331/index.html home page!
Reply
#11
LCD Wrote:
boriel Wrote:If you need FRAMES to update then you must use EI and not disable interrupts. But most of the time you needn't FRAMES, anyway. Changing the frames counter will always require EI (using interrupts). I don't understand exactly what where you trying... :?: :?: :?:
I want to play music in interrupts (in a different memory bank), switch to other song, and switch the music off. I also want to keep the FRAMES counter to re-RANDOMIZE events on the fly and keep the track how long ago the last event occured.
The easiest way at the moment seems to change the CALL in the Interrupt-Routine to a adrees contains RET (201).
Ok. The best way at this moment is to proceed as you said. In the future (I hope), you would write your own Interrupt routine in ZX BASIC Wink
Reply
#12
Start here:

<!-- m --><a class="postlink" href="http://www.worldofspectrum.org/faq/reference/128kreference.htm">http://www.worldofspectrum.org/faq/refe ... erence.htm</a><!-- m -->

At the very least it shows how memory works.

Right now, if you use the compiler cleverly, you could probably manually bank switch and use the extended memory yourself.

It would be nice if eventually the compiler did all that for you though - calling a function would work out what bank it was in, swap if necessary, and go there!

There are lots of considerations though. Just one example: We can only swap the top 16K of memory. So if code is running at an address higher than 49152 then anything it needs can't be in another bank of memory or we'll lose the code trying to access it. So you can't have code and data in separate banks if the code needs the data.

It's probably not a huge problem, and might be fixed by putting in some explicit compiler directives to say where code has to be.

For example:

BANK 2
<code for this 16K of memory>
END BANK 2

BANK 4
<code and data for this bank>
END BANK 4

And so on. If the code or memory requirements of any specified BANK -> END BANK are greater than 16384 bytes, then the compiler should throw a fit and stop compiling.

Of course then there's memory contention to think about. On the +3 it basically any bank that isn't the standard is contended (Just 0 and 2 are not).

However, on any 128K machine, we do get memory from about 24,000 to 49152 available that isn't going to be switched out. That's a bigger chunk. Though everything below 32768 is contended memory, so a little slower. But, if we don't want to bank switch at all, we can still use somewhere from about 24,000 to 65535 comfortably anyway - just like 48K mode!

Note: If we do it using marked bank memory, we'll need to load it in in chunks from "Tape" so as to be able to put things in other banks of memory.

Oh yeah, this is going to get complicated. Perhaps get everything stable in 48K mode first? Smile
Reply
#13
It's more than time to revisit this. I find myself wanting to write programs that are bigger than 48K!

If they are modular, and register clean (and ZX Basic very nicely doesn't assume registers will stay put between SUB calls, so is register clean), we can bank swap all we need to. The compiler just needs to be willing to swap memory before jumping to routines in other banks.

As mentioned above, I propose:

Based on http://www.worldofspectrum.org/faq/refer...erence.htm

My proposal is this - compiler directives that lock memory address space. (Pretty much what I said above, yes)

e.g.:

#GLOBAL LOW
#GLOBAL CONTENDED
Lets you choose whether the compiler places global memory and heap into the low contended memory or bank 2


#BANK CONTENDED
This memory bank is basically bank 5 from the ORG address to 32767
Do we want alternate screen features in bank 7?
This memory is contended.

#BANK LOW
This is actually memory bank 2 from address 32768 to 49151
On a 128K/+2 This memory is uncontended.
On a +2A / +3 This memory is uncontended.

#BANK HIGH 0
This is memory bank 0 and is in address space 49152 to 65535
On a 128K/+2 This memory is uncontended.
On a +2A / +3 This memory is uncontended.

#BANK HIGH 1
This is memory bank 1 and is in address space 49152 to 65535
On a 128K/+2 This memory is contended.
On a +2A / +3 This memory is uncontended.

#BANK HIGH 3
This is memory bank 3 and is in address space 49152 to 65535
On a 128K/+2 This memory is contended.
On a +2A / +3 This memory is uncontended.

#BANK HIGH 4
This is memory bank 4 and is in address space 49152 to 65535
On a 128K/+2 This memory is uncontended.
On a +2A / +3 This memory is contended.

#BANK HIGH 6
This is memory bank 6 and is in address space 49152 to 65535
On a 128K/+2 This memory is uncontended.
On a +2A / +3 This memory is contended.


So I'd expect the compiler, given a command like:

#BANK HIGH 6

To>

1> Compile this block to a separate binary (or tzx block)
2> Not allow this compilation block to exceed 16K
3> Know to jump to code to swap it in before jumping to any code in this block.


Further, we need a library command to manually swap these in for things like data access.

Finally, we need a routine that bank switches.

An example of a typical bank switch on the 128 is:
Code:
    LD      A,(0x5b5c)      ;Previous value of port
    AND    0xf8
    OR      4              ;Select bank 4
    LD      BC,0x7ffd
    DI
    LD      (0x5b5c),A
    OUT    (C),A
    EI

The principle is the same for all bank switching: change only the bits you need to.

When the routine comes back, switch it back to bank 0 presumably?

This routine would have to be in memory space that stays put.


But on the whole, this isn't actually difficult or rocket science - it could be done manually; but would be a pain, since you'd have to manually bank switch, then manually call the routine addresses. This is something a compiler should do for you, so you can call subroutines by name!
Reply
#14
LCD Wrote:I want to play music in interrupts (in a different memory bank), switch to other song, and switch the music off. I also want to keep the FRAMES counter to re-RANDOMIZE events on the fly and keep the track how long ago the last event occured.
The easiest way at the moment seems to change the CALL in the Interrupt-Routine to a adrees contains RET (201).

*resurrects an old thread*

Have a look at the code for BerksMan - it's all timing based, so I needed FRAMES to increase even if I was playing a sound. As a result, I wrote an IM2 routine that updates frames and returns, and instead of DI for sound I did IM2. This didn't actually affect the sound too badly, and meant that my timing keeps on going no matter what.

I went back to IM1 when the sound stopped.
Reply
#15
Any chance that memory management will be included?

We can't even carve off contended / uncontended space right now.

E.g. this doesn't work:

Code:
asm
org 26000
end asm

print "hello"

asm
org 32768
end asm

print "world"

Ideally, it could extend to spectrum 128 stuff - but I think being able to lock routines that are not time critical into lower memory, and ones that are into the upper 32k would help. (better yet, being able to choose lower/upper 1st half and upper 2nd half would be a bigger step to 128K compatibility). Right now all sub / function items seem to be glued to the end of the main loop regardless?
Reply


Forum Jump:


Users browsing this thread: 3 Guest(s)