stardot/b-em

Does b-em support mode 7 screen at &3C00 on a model B?

Closed this issue · 11 comments

This is definitely pushing my comfort zone, but I've been playing around with it. I couldn't find any sample code, but by experimentation I've come up with this:

MODE 7
PRINT "Hello"
$&3C00="Top"
A%=&3C00+24*40+34
$A%="Bottom"
FOR I%=&3C03 TO A%-1
?I%=32+(I% MOD 95)
NEXT
VDU 23,0,12,32,0,0,0,0,0,0
VDU 23,0,13,0 ,0,0,0,0,0,0
REPEAT UNTIL FALSE

On b-em this leave "Hello" on the screen, if I run it on jsbeeb I get a screen full of text with "Top" at the top left and "Bottom" at the bottom right. I haven't tried this on real hardware; I understand it will only work on a model B anyway.

I've attached a bootable zipped .ssd of the above program for convenience:
m7-3c00.zip

If this is a bug in b-em, I suspect the problem is somewhere around the else branch of 'if (ma & 0x2000)' in video_poll(), but I really don't understand the hardware situation here well enough to actually propose a fix.

From your description it looks like JsBeeb has it correct. Here's a pic from a real model B
IMG_1012

Thanks very much for trying this out on real hardware, it's good to know this works there!

So here is an excerpt from the circuit diagram:
6845
So looking at the MA pins of the 6845 the mask 0x2000 in:

            if (ma & 0x2000)
                dat = ram[0x7C00 | (ma & 0x3FF) | vidbank];
            else {
                if ((crtc[8] & 3) == 3)
                    addr = (ma << 3) | ((sc & 3) << 1) | interlline;
                else
                    addr = (ma << 3) | (sc & 7);
                if (addr & 0x8000)
                    addr -= screenlen[scrsize];
                dat = ram[(addr & 0x7FFF) | vidbank];
            }

corresponds to the TTXVDU line. I'll have to trace where that goes.

FWIW there is some information (which goes a bit over my head) here: http://beebwiki.mdfs.net/Address_translation You've probably already seen that or it doesn't help here, but I thought I'd mention it.

Actually I had not see that so I am reading it now. In the meantime the TTXVDU seems to determine if a latch grabs the data from memory to feed to the SAA5050.

Here's a patch to get the Model B behaviour:

diff --git a/src/video.c b/src/video.c
index 910623e..1c2c9b5 100644
--- a/src/video.c
+++ b/src/video.c
@@ -898,7 +898,7 @@ void video_poll(int clocks, int timer_enable)
                 cdraw = cdrawlook[crtc[8] >> 6];
 
             if (ma & 0x2000)
-                dat = ram[0x7C00 | (ma & 0x3FF) | vidbank];
+                dat = ram[0x3C00 | ((ma & 0x800) << 3) | (ma & 0x3FF) | vidbank];
             else {
                 if ((crtc[8] & 3) == 3)
                     addr = (ma << 3) | ((sc & 3) << 1) | interlline;

That was quick! That works, thanks! Sorry to state the obvious, but just in case you have overlooked it: I assume this actually needs to be done only if we're in model B mode, because at the moment it makes the test program "work" on a Master as well and based on what I've picked up from stardot that's not how real hardware behaves.

I don't actually know if the B+ should support this or not...

I don't know about the B+. I didn't want to test the MASTER boolean for every character to here's a patch that takes account of whether it's a master or not but only does the test when the CRTC register is set.

diff --git a/src/video.c b/src/video.c
index 910623e..374e0da 100644
--- a/src/video.c
+++ b/src/video.c
@@ -32,7 +32,7 @@ int crtc_i;
 
 int hc, vc, sc;
 static int vadj;
-uint16_t ma;
+uint16_t ma, ttxbank;
 static uint16_t maback;
 static int vdispen, dispen;
 static int crtc_mode;
@@ -64,6 +64,8 @@ void crtc_write(uint16_t addr, uint8_t val)
             vdispen = 0;
         if (crtc_i == 8)
             set_intern_dtype(vid_dtype_user);
+        else if (crtc_i == 12)
+            ttxbank = MASTER ? 0x4000 : (val & 0x8) << 11;
     }
 }
 
@@ -898,7 +900,7 @@ void video_poll(int clocks, int timer_enable)
                 cdraw = cdrawlook[crtc[8] >> 6];
 
             if (ma & 0x2000)
-                dat = ram[0x7C00 | (ma & 0x3FF) | vidbank];
+                dat = ram[0x3C00 | ttxbank | (ma & 0x3FF) | vidbank];
             else {
                 if ((crtc[8] & 3) == 3)
                     addr = (ma << 3) | ((sc & 3) << 1) | interlline;

Thanks, that works! There's not much difference from a hardware perspective, but I've been testing this with the tidied up variant of the code I posted on stardot here as well as the code in the first post in this thread.

The patch to get this working on a B+ is merged to master. I am just waiting to hear from someone with a B+ whether this Mode 7 at 3C00 works on a B+ or not.

Thanks to Richard B (rmbrowngr) from stardot.org.uk forums for testing this on a B+. The trick for Mode 7 at 3C00 does not work on a B+. Commit 0b708a6 implements this.