Jeroen Janssen wrote:
[snip]
> Anyway, I'm still not sure how I can do the host <-> guest video memory transfer...
>can I "map" a block of memory from the
> host into the guest somehow?
Yes you can BUT don't worry about that just yet because
not-in-fullscreen mode is way more important (because it's needed
anyways, for example, so that the guest and host can be in different
video modes, so the host doesn't need to be suspended periodicly, and so
Plex86 sessions can run in the background, like when there's multiple
sessions simultaneously) then fullscreen mode.
So here's what you need to do: study VGA.CC, mainly the way it handles
memory writes in mode 13h, and study the way it inter-operates with
GUI.CC (don't bother checking the GUI.CC sources; just see what it
calls).
I tell you what. I'll help you out. I'll write the code if you do all
the dirty work.
You'll need to test it in plex86 because I'm using bochs which is
compatible from the point of view of interacting with the GUI for the
following reason: we don't need to map the host's memory! For linear
framebuffering you need to do that, but not just yet. "Banked" SVGA
video modes use the A0000..AFFFF region (some video cards allow the use
up to BFFFF) and select which bank they wish to use.
Note that BIOS support in banked video modes is mandatory but not just
yet. For now, let's get it to just plain work.
Here's what we need to do: pick an SVGA video card that is common and
model our "pre-chipset" driver after it. We don't need to make it
compatible, but need to make it similiar enough so that it can be made
compatible some time in the future with a real chipset (why not the S3
Trio32? I got a Trio64 and older is easier and it's what VPC does... so
why not?) ..but not yet.
Basically a banked video mode works almost precisely the way mode 13h
works. The main difference is, the resolution is bigger, it isn't
limmited to 256 colors (but we'll begin with that anyways), and you can
choose the 64KB bank it's in (you can't do that in 320x200-256 colors..
multiply 320x200: you get 64,000. So you can't change the bank. But
don't worry about that; it's unrelated an VGA-only [not SVGA related]).
Now let's not make this any more perfect then VGA.CC is, because that'd
be silly since we're at VGA.CC's mercy anyways. For example, the
vertical retrace timing will be totally faked, and the mode-x
640x400-256 color will NOT work, (at first anyways), etc.
I wish we could do this under GPL, since DOSEMU has precisely what we
need, and it's been tested for years and works. It even works with real
video cards!!! (I use bochs under Windows with my S3 video card and it
uses the actual BIOS. It directly interacts with the real hardware and
the S3 drivers emulate the S3 it when its in the background... at least
I think it does).
Now here's something I'll do.
I'll use my S3 and set the video mode to 640x480-256 color. I'll use the
BIOS to plot a pixel on the screen at 0, 0 and then use the BIOS to plot
a pixel on the screen that has 65536 = 640 * x + y where x and y are the
numbers I'll give to the BIOS INT 10h handler.
This is the real S3 BIOS; I use it directly. I modified VGA.CC and my
DOS port of the GUI so that it just accepts keyboard I/O; VGA.CC sends
I/O data and video screen data it receives to the "physical"
locations... but not _physical_ when Windows is running it in a window;
e.g. when its in a VGA mode that the Windows driver knows how to
virtualize and copy to the window.
Now I'll "peep" at the I/O's that the BIOS does. Then I'll do the same
thing again at (1, 0) and at 65537 = 640 * x + y.
By repeating that maybe a dozen times and analyzing the different I/O
requests the BIOS does, I'll be able to see what's _different_ about
what the S3 SVGA BIOS is doing.
I already did this to figure out how a different VGA BIOS plots a pixel
on the screen in 640x480-16 color mode... crazy shit, you wouldn't
believe all the I/O it does for one little pixel in that mode. :-)
Anyways by seeing what's different I'll see how to change banks.
Then we'll make a pre-chipset that can ONLY change banks and do nothing
else, and ONLY in 640x480-256 color mode.
This is a "roadmap" to full (or at least "fuller" e.g. enough to run
Windows drivers in that mode).
IMHO, this is a good idea because everyone's already using 640x480-16
colors and as Kevin mentioned it's way slow. 256 colors is faster, even
if it has to change banks... 640x480-16 has to change "banks" (a
different kind of banks; they're called, "planes") anyways.
Now I'm not gunna see what the hell my S3 SVGA BIOS does to set that
video mode.. I don't care, but we need to know when to _leave_ the SVGA
video mode.
I recommend we do this, on the GUI level at first, rather than the
VGA.CC level.
That is to say the following:
Whne GUI.CC realizes there's a video mode resolution change, we'll see
if we're currently in an SVGA video mode, and if we're switching to a
VGA mode. If so, call the pre-chipset "quit svga mode" code. It cleans
up.
You figure out how to implement that. Maybe have a variable that says if
we're in an SVGA mode or not.
I'll get things working on the I/O level and you get things working on
the BIOS level.
Fair?
You probably know more than me on the BIOS level anyways (obviously you
do).
Here's a diagram of an organization example:
VIDEO.CC HELPERS are at the highest level of abstraction. They, along
with VGA.CC (see below), tell VIDEO.CC what I/O ports they wish to use
and VIDEO.CC will decide what's going on.
||
VIDEO.CC: we need to make this. It will receive VGA I/O and writes to
VGA video memory. In linear modes, this will provide an area of memory
that video accesses will go to. Thus for VGA mode 13h, writes to VGA
video memory will NOT be emulated, but will go to an area of memory.
When the GUI needs to draw to the plex86 window (I've never seen the
plex86 window. I got an error message when I tried to use it and haven't
tried since; in fact I bought a 40 GB hard disk I was going to use with
Linux but, couldn't use plex86, so never bothered to use the hard disk!
I'll get around to it... tsk tsk..) Anyways when the GUI needs to draw
the plex86 window, it will just read that area of linear 'video' memory
to find out how the thing is supposed to look. It doesn't need to know
what tile has changed unless it's running remotely or something...
Now a similiar thing will happen for SVGA linear video modes, like
640x480-256 colors. Anything that doesn't require performing some kind
of operation for every write (stupid VGA banked modes.. in plex86,
mode-x is slower than regular mode 13h [320x200-256 mode!])
||
Plex86, Bochs, whatever (absolute lowest level)
Now a note about VGA.CC: it is a helper just like SVGA.CC will be, for
VIDEO.CC. VIDEO.CC has "clients", like VGA.CC, which will request I/O
ports, memory, etc., that they might demand later when they're active.
Thus VGA.CC will tell VIDEO.CC that it intends on using the range
A0000..BFFFF at some point in the future. VIDEO.CC will register that
range of memory, "on behalf" of VGA.CC.
SVGA.CC might tell VIDEO.CC that it could use that range of memory, too.
VIDEO.CC will decide who gets what. VGA.CC starts out with everything,
and it is responsible for "passing" its rights on to another client.
This works as follows: rather than PANICing if VGA.CC receives an
unknown write to one of its I/O registers, it will tell VIDEO.CC that it
doesn't understand something.
VIDEO.CC will then PANIC on VGA.CC's "behalf", if none of its other
clients (like SVGA.CC) have told it that they "listen" on that I/O port
to see if they are to become active.
So for example, if I try to change the bank in text mode, VGA.CC will
realize it doesn't know how, and VIDEO.CC will realize that SVGA.CC
listens on that port. It will then ask SVGA.CC, "are you to become
active if you get this value on this port?" And SVGA.CC wil lsay, "No.
Whilist it is true, sire, that I recognize that request, I do not honour
it when I am inactive and take it to mean, 'time to become active.'"
Then VIDEO.CC will panic (or ignore it if it wishes).
For now we'll make up an I/O sequence to "unlock" SVGA.CC. For now, it
might as well be a made up port; we'll change it later. So you send 1 to
port 1234h to unlock SVGA.CC operations and send 0 to lock them.
In fact, we'll make it so that SVGA.CC tells VIDEO.CC that it listens on
port 1234h to decide when to become active.
Now the SVGA BIOS extension will do this: see if the video mode is a
set-video-mode to 110h or whatever it is (I forget) for 640x480-256
color. That's all it will do for now. If it is, it will unlock SVGA.CC
by sending 1 to port 1234h, and then it will send 2 to port 1234h,
which, when unlocked, means: set video mode. WHen unlocked, we'll make
ports 0x1238..0x123f "sticky" in that you can write to them, and when
you read, they remember their old value).
Now here's what the BIOS will do to set video mode 640x480-256 colors:
outportw(0x1238, 'VBE1');
outportw(0x123a, 640);
outportw(0x123c, 480);
outportw(0x123e, 256);
outportb(0x1234, 2);
See, when we get the 2 command, we'll consult the 16-bit words that were
stored in 1238h..123eh, and set the video mode accordingly.
How about leaving SVGA video modes, e.g. what if the user sets the video
mode back to a VGA mode?
Well, then the SVGA video mode will receive some commands it doesn't
understand, and imform VIDEO.CC that it doesn't understand them. Then
VIDEO.CC will see if anyone else listens on those ports.
VGA.CC will be checked last by VIDEO.CC, after all other checks. VGA.CC
will listen on all VGA ports and will hence become active.
Before doing that, VIDEO.CC will tell the current video user, "adios, I
found someone who understands that, so yer going to have to lock
yourself up [e.g. what if the user left it unlocked?] and stop using any
memory etc. you've been using, etc."
When the former happens, VGA.CC will automatically imform GUI.CC about
the video mode change, like it does already.
Er.. I wonder if anyone here uses IRC or ICQ or something? I wonder if
that'd save some time cause there'd be no need to wait for responses.
Hmm, we could work on the program and ask questions, swap files, etc. at
the same time. But none of it would end up in the newsgroup.. oh well it
was just a thought.