CPCWiki forum

General Category => Programming => Topic started by: kelp7 on 09:18, 18 November 14

Title: Streaming level data from cassette
Post by: kelp7 on 09:18, 18 November 14
Hi,


Just wondering whether it would be possible, perhaps during a scrolling shoot-em-up or something, to stream the level data from cassette (if perhaps the level data were bigger than available memory this would be one way of getting around that to have huge levels)? Would there be a problem doing this if you had interrupt-driven graphics effects? Would you have to keep stopping and starting the tape motor?
Title: Re: Streaming level data from cassette
Post by: Gryzor on 11:54, 18 November 14
For one thing, even if it was done technically-wise, it'd be unpractical because you'd have to rewind after each play...
Title: Re: Streaming level data from cassette
Post by: kelp7 on 14:17, 18 November 14
Heh, yep. Rubbish idea :) It was very early when I posted this and my brain wasn't functioning.... silly idea really, I just wondered what would get in the way of it working and, for instance, not spoiling interrupt driven graphics (or rather the interrupts not getting in the way of getting data from tape). Yep, forget I said anything  ;D
Title: Re: Streaming level data from cassette
Post by: steve on 15:25, 18 November 14
This thread may help Breaking Baud (http://www.cpcwiki.eu/forum/demos/breaking-baud/)
Title: Re: Streaming level data from cassette
Post by: steve on 15:45, 18 November 14
I think there was a game which loaded a simple game for the user to play whilst the actual game was still loading from tape, I do not remember which machine this was for though.
Title: Re: Streaming level data from cassette
Post by: CraigsBar on 16:06, 18 November 14
Quote from: steve on 15:45, 18 November 14
I think there was a game which loaded a simple game for the user to play whilst the actual game was still loading from tape, I do not remember which machine this was for though.
C64 I think.
Title: Re: Streaming level data from cassette
Post by: robcfg on 16:14, 18 November 14
Rescue From Atlantis (http://cpc-power.com/index.php?page=detail&num=1788) let you play Mastermind while the game was loading.
Title: Re: Streaming level data from cassette
Post by: opqa on 16:20, 18 November 14
Possible it is of course, not easy, but certainly possible (see Breaking Baud demo pointed earlier). It seems an interesting idea to me, altough rather limited because of the reasons you've been told and some others...

The need to rewind every time you restart the game could be overcome by using a separate tape and a gameplay that lets you re-start from the beginning of each level.

Other kind of problems that may arise... Starting/stopping the tape motor, for instance, should only be done between separated blocks of data, different levels for instance. This is because any realiable algorithm that reads data from tape needs to perform some kind of syncronization with the beginning of a block of data, after this syncronization phase the rest of the block must be loaded continously at a fixed rate. The BIG advantage of the tape is that you can desing and use any desired block format at any bit-rate, as slow as needed.

With this constrains in mind, and being practical. The only use I see is to design a multi-stage game that has enough space in RAM to accomodate 2 stages, the one being played, and the next one. This way you could try to load the next stage while playing the current one, thus avoiding or reducing the wait time between stages.

There other possibility I see, which is technically more challenging and practically more limited. Is to design a one-stage game which is continously loading data from the tape, all in a single block. This kind of game would have the following limitations:
All in all, I even think that this second option would still be an interesting concept. It would allow the programmer to design an extremely long, continous, and at the same time diverse world. Depending on the selected bit-rate of course, that would also affect the amount of CPU usage.
Title: Re: Streaming level data from cassette
Post by: SyX on 16:59, 18 November 14
The idea is not crazy, i like a lot, but for tape is not practical, you are going to need extra hardware.

NOW, you have a few options for streaming:
1.- From a floppy disk as Batman demo and you can use the arnoldemu's loader :)
2.- Use a minibooster or another CPC serial port, then you can use a PC as a big tape, without those tape problems. I explained in the shoutbox how to control a DVD player from a minibooster in the CPC for playing to Dragon's Lair DVD.

In a near future (soon i promise ;)):
1.- HDs expansions.
2.- Ethernet expansions.
Title: Re: Streaming level data from cassette
Post by: ralferoo on 10:13, 19 November 14
Back when I was writing Breaking Baud, I was toying with the idea of streaming the graphics for a canabalt type game from tape as a proof of concept.

In the end, I discounted it because in addition to the "soft problems" like excessive rewinding, there are some severe technical reasons too...

* On a 664/6128, you can't guarantee that the motor control is available, so realistically any game needs to be "on rails" and load data at exactly the rate needed for the game. Also, this makes dealing with read errors disruptive to game play.
* The absolute idea killer - changing the direction of the AY port turns off the tape motor. In practice, this makes a very loud clicking noise, but also slows the tape down and over time will probably damage the tape deck. So, why do you need to change the direction of the AY port? Well, simply - to read the joystick or a column of the keyboard the port needs to be in read mode and to play music or choose which column to read the port needs to be in write mode. So, it's possible to make a silent game that's joystick only or it's possible to make a demo with sounds, but it's not possible to have user input, play sounds AND load from tape at the same time.
Title: Re: Streaming level data from cassette
Post by: kelp7 on 15:39, 19 November 14
Thanks, that explains quite a lot. Some people on here would be aware possibly anyway, but I'm not strictly coding for the CPC. It's a Z80 machine but not CPC. I'm sure I would face some or all of the problems you described anyway and just wanted to run the idea past some folks here as this is one of the best communities I've come across for thrashing out ideas or code with :) To get any kind of decent graphics effects on the machine I have you simply have to employ interrupts. And I think once that comes into the equation it really ruins the idea of even attempting to stream scrolling level data from tape...
Title: Re: Streaming level data from cassette
Post by: opqa on 16:03, 19 November 14
Why not include the tape read routines within the interrupts? Depending on the selected encoding bit-rate and the frequency of the interrupts it might be possible and would even be easier. In the CPC for instance there is an interrupt every 1/300s, so in principle it should be possible to retrieve data at 300bps.
Title: Re: Streaming level data from cassette
Post by: kelp7 on 16:36, 19 November 14
Hmm, could be an option. I think perhaps I'll try it at some point. If I get anywhere, i'll post back here, thanks everyone!
Title: Re: Streaming level data from cassette
Post by: Prodatron on 17:05, 19 November 14
Quote from: SyX on 16:59, 18 November 14In a near future (soon i promise ;) ):
1.- HDs expansions.
2.- Ethernet expansions.
Can't wait for it!  :P :P :P
Title: Re: Streaming level data from cassette
Post by: Gryzor on 19:31, 19 November 14
Quote from: robcfg on 16:14, 18 November 14
Rescue From Atlantis (http://cpc-power.com/index.php?page=detail&num=1788) let you play Mastermind while the game was loading.


Hm, tried the CDT from CPC-Power and it starts loading, draws a basic UI for the Mastermind game and then just goes on loading till the end of the tape, where nothing happens... That's in WinAPE. Anyone's got an idea?
Title: Re: Streaming level data from cassette
Post by: robcfg on 19:53, 19 November 14
Take a look at the game manual at cpc power. I don't remember quite well, but I think you can just press numbers to play while loading.
Title: Re: Streaming level data from cassette
Post by: pacomix on 12:50, 20 November 14
Quote from: SyX on 16:59, 18 November 14
The idea is not crazy, i like a lot, but for tape is not practical, you are going to need extra hardware.


   As previously opqa said, it should be possible to stream data at 300bps (in the case we only take one bit per interruption). The problem? Having to rewind is not nice... What if we use a looping cassette? :D Side A main program... Side B program stream data...
Title: Re: Streaming level data from cassette
Post by: SyX on 17:31, 20 November 14
Quote from: pacomix on 12:50, 20 November 14
   As previously opqa said, it should be possible to stream data at 300bps (in the case we only take one bit per interruption). The problem? Having to rewind is not nice... What if we use a looping cassette? :D Side A main program... Side B program stream data...
Sure, but it's not practical as everybody has written, i don't say it was not possible.

While using a fast device or a serial/network port for streaming  is easy and straightforward  :P

A few years ago, i made a videoplayer for CPC using an USB pendrive for streaming the videos as a test bank for converting Laser disc arcade games and it was a lot of fun :)
Title: Re: Streaming level data from cassette
Post by: ralferoo on 20:52, 21 November 14
Quote from: kelp7 on 15:39, 19 November 14
Thanks, that explains quite a lot. Some people on here would be aware possibly anyway, but I'm not strictly coding for the CPC. It's a Z80 machine but not CPC. I'm sure I would face some or all of the problems you described anyway
I'm not sure how your target machine is wired up, but you might well not have this problem. It's only an issue for the CPC because the tape motor is controlled by the PPI AND also the AY chip's databus is connected to a port on the PPI AND the keyboard is read through the AY (and hence through the PPI too). This is a particularly silly bit of design really, and e.g. the MSX just has the AY connected directly to the Z80 databus with the BC1 and BDIR connected to the address lines, so wouldn't suffer this problem.

QuoteTo get any kind of decent graphics effects on the machine I have you simply have to employ interrupts.
I disagree, but it totally depends on what you're comfortable with.

It's perfectly possible to work without interrupts at all if you can read the VBLANK status via the CPU, so you could write your code as: DO WORK, POLL AND LOOP. This style actually works very well if you want to interleave it with carefully timed code (such as reading the tape).

Another trick I've used in the past is to disable interrupts, then get to a "safe moment" and then do EI: NOP *n: DI. If the interrupt path is taken, it'll happen at a well known time in your cycle counting. You can adjust the number of NOPs needed so that you can return to your cycle counted code at the same logical time as you left it.

Quote from: opqa on 16:03, 19 November 14
Why not include the tape read routines within the interrupts? Depending on the selected encoding bit-rate and the frequency of the interrupts it might be possible and would even be easier. In the CPC for instance there is an interrupt every 1/300s, so in principle it should be possible to retrieve data at 300bps.
This wouldn't work reliably unfortunately. I go into more detail about this in the tech docs for Breaking Baud, but essentially the issue is that the tape might be playing slightly slow or fast at any point, so you need to sample several times faster than the target baud rate. Assuming (for the sake of argument) a 250 bps data rate, you're expecting a nominal 4ms pulse length. If you sample at exactly 4ms, you might (in the worst case) miss a 3.99ms long pulse entirely. Equally, you could interpret a 4.01ms pulse as an 8ms pulse. Consider these timing diagrams (a missed pulse, a pulse that is read as being too long, a pulse where the it'll be read reliably:


......|.XXXXXXXXXXXXXXXXXX.|....
.....X|XXXXXXXXXXXXXXXXXXXX|X...
......|......XXXXXXXXXXXXXX|XXXX


So, essentially, the problem you're trying to solve reading a tape is:
* for constant (and slow) bitrate, finding the midpoint of the pulse so that you can reliably sample it (and bear in mind that if the tape is 5% too fast, that midpoint will be constantly moving)
* for variable bitrate, determining the length of the pulse.

As you can see, the first problem is actually slightly harder than the second, which is why most tape encoding schemes use the second in practice. The second scheme has an error margin of +-2 samples, so the more frequently you sample the data, the better confidence you have of the target baud rate.

Breaking Baud samples has a nominal "short pulse" of 3 times the sample period and a nominal "long pulse" of 9 times the sample period, and it treats a pulse lasting 1-5 samples as short and 7-11 samples as long. Note that because the sampling is relatively infrequent, I can't have a long pulse that's double the length of a short pulse because the +-2 samples error means that any pulses that were measured as 4 or 5 samples long could actually be either long or short. If it ran at a slower baud rate or a faster sample rate, the long pulse could be reduced to double the length of the short pulse (and the short pulse would have to be at least 4 samples long).

Not sure if that all makes sense, but ask if you need more info... :)
Title: Re: Streaming level data from cassette
Post by: AMSDOS on 12:28, 22 November 14
Quote from: Gryzor on 19:31, 19 November 14

Hm, tried the CDT from CPC-Power and it starts loading, draws a basic UI for the Mastermind game and then just goes on loading till the end of the tape, where nothing happens... That's in WinAPE. Anyone's got an idea?


I had big problems loading one of my Firebird Loader games with WinAPE which I got from CPC-Power. The advise I got back about this was to use WinCPC, which I did and had the CDT loading without any issues.
So it seems WinAPE has issues loading some of the more complicated CDTs, though I had no problems with the Standard Stuff when submitting BASIC type-ins, AA Covertapes are also fine, though I'm not sure about the Speedlock games.
Title: Re: Streaming level data from cassette
Post by: ralferoo on 18:11, 22 November 14
WinCPC also has (different bugs) for tape reading..

I reported this to Flynn in September 2011 and again in November 2013, neither time my email was answered or even acknowledged, so it's pretty clear that he's not doing any development on WinCPC any more even for simple fixes with clear repros... :(

Quote
Hi Flynn,

Not sure how actively you're maintaining WinCPC at the moment, but I just found a bug in the CDT handling of direct recording blocks (type 0x15).

Basically, for direct recording blocks, the emulator correctly plays the noises from the tape file, but modifies bit 5 of port &f500 rather than bit 7.

With the attached test example, I've hooked a real CPC up to the speakers of the emulator and can run |tape:run" on both. If I then play watch_tape-plain.cdt, it loads the border flasher program (see asm), and then if I play nulls-plain.cdt I can see the border flashing on both emulator and CPC. If I play nulls-gcr.cdt, the border only flashes on the CPC not the emulator.

Regardless of whether I read tape data using ld a,#f5:in a,(0) or ld b,#f5:in e,(c), the data oscillates between #5e and #7e for the -gcr.cdt and between #5e and #de for the -plain.cdt.

This is with 0.9.26 build 4102 which I think is the latest one even though it's quite old now...

Cheers,
    Ralf.

Atatched is a copy of the latest repro if you want to see this for yourself...

BTW, for WinAPE, I found that if you convert the cdt to wav with an external utility, things load in WinAPE more happily from wav than cdt files...
Title: Re: Streaming level data from cassette
Post by: Gryzor on 20:21, 22 November 14
Yeah, I've contacted Flynn a few times myself, he's probably ignoring all emails related to WinCPC. What a shame...
Title: Re: Streaming level data from cassette
Post by: AMSDOS on 22:05, 22 November 14
I guess that's why we have a range of Emulators for that reason.  :laugh:


But personally I gave up on trying to load "Thunderzone" with Winape, which just seemed like there was lag and couldn't pick up the blocks quickly enough. Who knows it might of been because of my old computer and Winape sometimes slows down, but after downloading WinCPC and loading it through that (both standard and emulator speedup), the game loaded without error.
Title: Re: Streaming level data from cassette
Post by: kelp7 on 18:25, 23 November 14
Quote from: ralferoo on 20:52, 21 November 14I disagree, but it totally depends on what you're comfortable with.


I'm afraid, interrupts are the only way to get any kind of interesting graphics on the machine. I really appreciate all of your advice :) but I'm afraid the machine I have has no ability to display graphics in the first place (other than the ASCII and extended-ASCII character set which is set in stone). There is one interrupt and this happens via two 8253 counters wired together. The 8253 is a pain to code for but certain effects are achievable. If you don't use interrupts there is very little you can do to make a game look any different from, pretty much, any other game on the computer as you will only be able to use the graphic characters (8x8 character set) that is provided on the ROM. You can't change these characters as it is impossible to access the chip where they are stored (other than to read it, which you don't actually do yourself as a programmer anyway, it's done 'behind the scenes' by the internal wiring of the computer).


Thanks though, the rest of your advice is exceptionally interesting!

Title: Re: Streaming level data from cassette
Post by: opqa on 19:58, 23 November 14
Those chips seem to be quite flexible, if you can program a dedicated interrupt for tape reading and actively adjust its time interval then the problems rafelroo mentioned could be overcome. This is a vage idea but you could use something like this:
GGGGGPPPGGGGG
      |
With G being a pilot wave and P being the bit(s) pulse, if you can freely program the interrupts you can synchronize at the beginning to enter some time before the pulse, then wait for it measuring the elapsed time, and re-adjust the next interrupt if needed, by delaying or advancing it.
This can't be done on the CPC because interrupts can only be delayed, and only within a frame. Every frame with the VBL signal the interrupt counter is always resetted by the hardware.


Title: Re: Streaming level data from cassette
Post by: Executioner on 02:38, 26 November 14
Quote from: AMSDOS on 12:28, 22 November 14
So it seems WinAPE has issues loading some of the more complicated CDTs

It shouldn't have any problems, but I think there is a problem with the CDT spec and resetting the output bit state between blocks. I tried both ways, either keep or reset the bit state, and both caused some CDTs to fail. I'm not 100% sure if this is the problem as it has been mentioned that using CDT2WAV seems to work with most (All?) CDTs.
Title: Re: Streaming level data from cassette
Post by: kelp7 on 12:56, 26 November 14
Quote from: opqa on 19:58, 23 November 14
Those chips seem to be quite flexible, if you can program a dedicated interrupt for tape reading and actively adjust its time interval then the problems rafelroo mentioned could be overcome. This is a vage idea but you could use something like this:
GGGGGPPPGGGGG
      |
With G being a pilot wave and P being the bit(s) pulse, if you can freely program the interrupts you can synchronize at the beginning to enter some time before the pulse, then wait for it measuring the elapsed time, and re-adjust the next interrupt if needed, by delaying or advancing it.
This can't be done on the CPC because interrupts can only be delayed, and only within a frame. Every frame with the VBL signal the interrupt counter is always resetted by the hardware.


That does sound good but, yeah, as much as the 8253 is quite flexible, it's also tricky to code for as any change to the counters only happens after one 8253 clock cycle. Your code could trigger the change to the counter anywhere between the start or end of that clock cycle (a bit like when you wait for vsync using a bit of code where the vsync could happen anywhere in your lines of code which are carrying out the check).
Title: Re: Streaming level data from cassette
Post by: AMSDOS on 09:58, 01 December 14
Quote from: Executioner on 02:38, 26 November 14
It shouldn't have any problems, but I think there is a problem with the CDT spec and resetting the output bit state between blocks. I tried both ways, either keep or reset the bit state, and both caused some CDTs to fail. I'm not 100% sure if this is the problem as it has been mentioned that using CDT2WAV seems to work with most (All?) CDTs.


Yes I converted the program with Firebird loader back to WAV format and loaded the program in WinApe without error. So say you suggest the CDT spec might have a problem, I haven't had problems on the standard stuff, so it perhaps suggests the more unusual loaders like Firebirds creates problems.
Powered by SMFPacks Menu Editor Mod