stardot / beebem-windows

BBC micro emulator for Windows
http://www.mkw.me.uk/beebem/
Other
90 stars 36 forks source link

BeebEm doesn't support mode 7 screen RAM at &3C00 on a model B; could this be added? #66

Closed ZornsLemma closed 4 years ago

ZornsLemma commented 4 years ago

By fiddling with the CRTC registers it's possible to persuade a model B to use &3C00 instead of &7C00 for mode 7 screen RAM. I've written a bit more about this on stardot (https://stardot.org.uk/forums/viewtopic.php?f=54&t=20149) and there's a "real" program which uses this feature attached to this stardot post: https://stardot.org.uk/forums/viewtopic.php?f=2&t=19975&start=300#p292963

Would it be possible to add support for this to BeebEm please?

chrisn commented 4 years ago

Yes, I'm happy to take a look. For reference, here is the corresponding B-Em issue.

chrisn commented 4 years ago

I'm working on a fix (studying the B-Em change is helpful), but I have one question. Do you know the behaviour on a Model B with Integra-B expansion board?

ZornsLemma commented 4 years ago

Thanks for taking a look at this! I don't know the answer, but I've posted (at the bottom of the "real" program thread mentioned above) on stardot so I hope Ken will be able to advise.

ZornsLemma commented 4 years ago

Incidentally you've probably seen from the b-em discussion/code, but it was established on stardot with help from a B+ owner that this doesn't work on a B+ (or a Master). (https://stardot.org.uk/forums/viewtopic.php?f=4&t=20174&p=283745&hilit=b+3c00#p283745)

chrisn commented 4 years ago

Yes, I've seen that, so B+ and Master behave as before, it seems.

The other thing I've just found is this code, which wraps addresses in Mode 7 at &8000. I'm wondering whether this needs to wrap at &4000 in this TTX VDU mode.

ZornsLemma commented 4 years ago

That's an interesting observation. I'm assuming that would come into play if the CRTC were programmed to start the screen at (say) &3C28 or &7C28 in order to perform hardware scrolling. I'm afraid I don't know the answer and I don't have any real hardware to test on either.

Edit: What I can say is that my code to make the Acorn OS work with the screen at &3C00 defines a text window to stop the OS trying to hardware scroll the screen in the first place. But this isn't to say that the hardware scrolling wouldn't work if properly programmed by custom code, just that I couldn't persuade the OS to do it.

ZornsLemma commented 4 years ago

BeebWiki seems to be down at the moment, but it's possible the (rather over my head) page http://beebwiki.mdfs.net/Address_translation mentioned in the b-em github issue contains an answer.

mungre commented 4 years ago

I wrote this a while ago. It's based on a bunch of stardot posts but I haven't seen it all in one place:

In beeb modes 0-6 you need to add 8 to the current screen address to move to the next character cell, but in teletext mode 7 you only need to add 1 to the address.

The 6845 doesn't know anything about this. It always adds 1 to its address to move to the next character cell.

So the beeb uses the 14-bit address generated by the 6845 in one of two different ways. If the top bit of the address (value 0x2000) is set then the beeb treats it as a mode 7 address otherwise it treats it as a mode 0-6 address. (Note that this is independent of the teletext select bit in the video ULA.)

In modes 0-6 you have:

Unwrapped real memory address = (a_6845 << 3) | (scan line number & 7)

where a_6845 is the address generated by the 6845 and the scan line number is the line number within the current character row, mostly 0-7. If the scan line number exceeds 7 (as in the gaps between rows in modes 3 and 6) then the hardware blanks the video output (and suppresses any memory access?).

This explains why the 6845 is programmed with the desired screen start address divided by 8.

If the unwrapped memory address exceeds 0x7FFF then the hardware adds an adjustment factor to wrap the address round to the start of the screen. The adjustment factor is defined by bits 4 and 5 of the addressable latch, which is programmed using the System 6522 (AUG page 419).

An address generated by the 6845 in modes 0-6 will be between 0x600 and (roughly) 0x19FE. Note that this never has the 0x2000 top bit set.

In mode 7 the 6845 is programmed with a start address between 0x2000 and 0x23FF to display data from 0x3C00 to 0x3FFF or with a start address between 0x2800 and 0x2BFF to display data from 0x7C00 to 0x7FFF.

Real memory address = (a_6845 & 0x800) << 3 | 0x3C00 | (a_6845 & 0x3FF)

This handles wrapping at 1K by ignoring the 0x400 bit and seems to match Tricky's description of the real behaviour. This also matches the behaviour of the b2 emulator.

Because the scan line number is ignored you get the same memory addresses repeated for every scan line in a character row.

If the 6845 is programmed with a start address of 0x2400 it accesses memory from 0x3C00 to 0x3FFF then 0x7C00 to 0x7FFF giving a 2K linear buffer.

Also, it might be interesting to try 6845 start addresses from 0x3000 upwards on real hardware. I would guess they behave the same as addresses from 0x2000.

chrisn commented 4 years ago

Thanks @mungre, that's really helpful. I've pushed a fix, and BeebEm now matches real hardware (and JSBeeb and b2).

For now, I've assumed the behaviour with Integra-B is the same as a standard model B. I'll wait for confirmation from Ken before closing this issue.

ZornsLemma commented 4 years ago

Thanks Chris, that's great news.

mungre - that was a really interesting collection of information, has it been posted on stardot or beebwiki or somewhere so it doesn't get lost? I suppose Google will probably find it in this issue now anyway.

kgl2001 commented 4 years ago

Using the mode7-3c00.ssd test disk from the first post in the stardot thread, a real beeb with IntegraB (in OSMODEs 0 & 1) behaves the same way as a standard beeb, reporting 'We're now in mode 7 with the screen RAM at &3C00...'. In this regard, the behaviour in BeebEm is wrong for both standard beeb & beeb with IntegraB. This doesn't surprise me, since BeebEm uses the same code for reading and writing standard screen memory (reading and writing IntegraB Shadow memory is obviously different).

chrisn commented 4 years ago

I've just tested the https://github.com/stardot/beebem-windows/commit/540218a6a78b035435a5b0661f2dc77485272792 fix with Integra B. In OSMODE 0 and 1 shows "We're now in mode 7 with the screen RAM at &3C00", and OSMODE 2 etc shows "Sorry BBC B only". So I'm happy that the fix is working correctly.

mungre commented 4 years ago

Cheers, I'm glad it was helpful. Beebwiki's poorly but I'll copy it there when it recovers.