** ** 0 0100010 $22
** ** 1 0010010 $92
** ** 0 0010100 $14
**** 1 0001100 $8C
** 0 0001000 $08
** 0 0001000 $08
** 0 0001000 $08
(Note, two adjacent asterisks are used to visualize a single pixel.)
Basically when the most significant bit is set the pixels get
shifted half-pixel right, instead of looking like:
** **
** **
** **
****
**
**
**
The Color (Half-Shift) mode doesn't really do the half-shifting I'm
after. Are here any AppleWin developers around to ask for providing
such new video mode?
--
Stanimir
The mode you mention "almost" does it.
Michael would be the guy to ask.
The video code is painfully obscure.
And hopefully going away some day ...
Cheers,
Nick.
The implementation I've worked with converts hires to a DHGR 560-pixel
screen first, then converts that to DHGR after the fact (or outputs it
in B&W when not in a graphics mode). This accounts for half-pixels in
hires along byte boundaries (e.g. a half-width orange pixel that
appears brown). Nick has the code if he wants it. ;-)
-B
That's the kind of implementation I would have expected, and
it should deliver the "half-pixel" shift the OP is looking for.
-michael
NadaNet 3.1 for Apple II parallel computing!
Home page: http://home.comcast.net/~mjmahon/
"The wastebasket is our most important design
tool--and it's seriously underused."
Yes, I think I even remember the behavior of shifted pixels
appearing half-width when at the byte boundary. It would be really
nice to see it in action with the emulator.
--
Stanimir
That's correct--and it gives rise to some peculiar "dark" colors
in color mode.
Thanks
The funny thing is, by the time I completely understand how it works, we'll probably rip it out and replace it with something not as obfuscated. :-)
Michael
It's the video emulation written in JACE, actually. You're welcome to
look at it, insult it, or ever improve it (god knows I want to do all
three of those, but never get around to it)
The color-shift logic is the only thing about the video output of JACE
that I find really "works" authentically. Like I said, I convert
successive bytes of HGR ram into DHGR and display accordingly. What
the emulator does currently is take two consecutive bytes of HGR data,
and convert it to four bytes (actually 28 bits) of DHGR data. Then
those are broken up into 7 pixels using a lookup of the 4-bit color
values. It captures the half-pixels correctly, and looks spot-on if I
rig the emulator to be B&W only (that will be an exposed feature once
configuration is done).
Otherwise the color conversion to RGB is a very lazy approach that
doesn't take into account neighboring pixels -- e.g. it only looks at
individual 4-bit windows to decipher their color, much like an Apple
RGB monitor does. Not very good when you look at games that took
advantage of NTSC artifacts, or have staggered pixels that should
appear mostly white such as text. **sigh** one day...
-B
You can get the NTSC effect you want by widening the lookup table
to include more bits preceding this pixel. Widening it from 4 bits
to 10 or 12 bits should capture all the NTSC goodness. ;-)
Of course, the table must be filled in with appropriate RGB values,
but I think that others have already computed that table...
Yes, I was just looking at this yesterday ...
"Jon Relay's Apple II Info Archives - Video Display Theory"
http://www.kreativekorp.com/miscpages/a2info/munafo.shtml
And others have populated the table for limited-bandwidth
chroma characteristics of NTSC, which produces the pixel
blending and other artifacts.
IIRC, some work was being done for the Apple II MAME emulation...
part of a possible general "NTSC monitor" emulation.
These past few days I've been taking (crappy/blurry iPhone macro) pictures of the color monitor and am slowly working out the physical measurements of the slot mask! I've been able to cheat by turning up the brightness (?) -- the 2nd dial from the left -- so that the normally black background becomes a faint red tint, and then put whole the thing into monochrome mode. :-) (I'll see if I can put some pics up so people can see what I am talking about.)
On my 12" (diag measurement) color monitor, the Apple displays 280 pixels taking up around a width of 9 1/4". Now all I need to next is to count the number of slot masks to determine the real dot pitch, and one of hardest parts will be over.
I've come to the conclusion that in order to emulate the NTSC natural blur, you need to know an accurate width and height of:
a) the width of the r/g/b that shines through a slot mask
b) the width of the black slot mask inbetween the RGB
c) the height of the r/g/b that shines throught a slot mask
d) the height of the black slot mask in between 2 scan lines
See the right side of this pic:
http://en.wikipedia.org/wiki/File:CRT_mask_types_en-de.svg
With a modern 1980x1080 resolution I think we can approximate NTSC electron blur + slot mask reasonably well. (Three HGR even pixel bleeds into approx 11 horz slot masks and 3 vertical slots)
Here is a top-down diagram to help visualize:
Apple HGR Even Pixels,
1 1 1
- - - - - - - - - - - - 11 slots mask
a A A b C C c d E E e
Visible lit phosphors of the slot mask
Legend
1 = $2000:5 (HGR mode)
a = mild color of the left Apple pixel
A = strong color of the left Apple pixel
b = faint color of the left and mid Apple pixel
c = mild color of the mid Apple pixel
C = strong color of the mid Apple pixel
d = faint color of the mid and right Apple pixel
e = faint color of the right Apple pixel
e = strong color of the right Apple pixel
Cheers
Michael
Have a look at Blargg's NTSC emulation libraries:
http://slack.net/~ant/libs/ntsc.html
Marc Ressl has improved on this I think, but I won't steal his
thunder.
Anyway, we still don't have handy tables to index into ...
Filtering seems to require many taps (= past output bits).
Cheers,
Nick.
...and the filtering is pretty complex compared to doing it once
and saving the results in a table.
There's the obvious tradeoff between fidelity to <1MHz lowpassed
chroma info and number of "560-mode" bits used to index. 12 bits
seems to be a reasonable compromise, with the table fitting in
just 16KB of cache.
12 "560-mode" bits covers 12/14 of a microsecond, which should be
plenty to handle the transient response of a 1MHz chroma signal.
Once a "long" implementation is created, it would be trivial to mask
the video lookup bits to determine how many are really needed to produce
realistic NTSC rendition.
I've taken a look at this -- it is nice, but not exactly the PQ I am looking for.
Methinks we need 2 rendering methods:
a) SDL / DirectDraw
b) DX / OpenGL - a 1.0 (2.0+?) pixel shader can do the NTSC processing "for free"
Thanks for the link though!
Cheers
Michael
I should also reiterate that the table lookup should be performed
after each shift of *one* bit, and that the lookup determines the
color of that particular "560" pixel on the display.
While the geometry of a particular CRT's shadow mask can be emulated,
it does not play a role in the color rendering when viewed from a
reasonable distance. The primary effect is a resampling of the pixels
at the shadow mask pitch.
Yeah, this has been a pet peeve of mine for a while now. I've implemented this tonight and uploaded a test version into the nightly build location. :-)
I've also uploaded some raw HGR test images that you can load into the debugger as well.
e.g.
F2
CTRL-F2
HGR2
F7
bload "mono560.hgr",4000
\
F9 ...
bload "gumball_machine.hgr",4000
\
F9 ...
Note: The mono560 is the DOUBLE HI-RES from SILICON SALAD.
e.g.
http://michael.peopleofhonoronly.com/dev/applewin/nightlybuild/AppleWin_SiliconSalid_Before.bmp
and
http://michael.peopleofhonoronly.com/dev/applewin/nightlybuild/AppleWin_SiliconSalid_After.bmp
@Nick, the video code is "less obscure" :-) I'll post my "AppleWin Video.cpp Demystified" notes sometime soon - the short version is that all the Draw*() code such as DrawHiResSource() are basically badly named.
CreateDIBSections() -> CreateVideoColorLookupTables()
DrawHiResSource() -> CreateHiResEnumarationBytes()
The 3728 x 512 (!?!?) "source" bitmap (g_pSourcePixels & g_pSourceHeader )
is REALLY this Color Enumaration Lookup Table for all the various video modes. It took me a while to figure out why the hell the code is doing this:
g_pSourceHeader->bmiHeader.biWidth = SRCOFFS_TOTAL;
Each scan line corresponds to one byte of the 256 possible permutations of a "pixel". Normally the height would be 256, but since each scan line is double for the TV mix mode, that explains the 512. The 3728 is a little trickier, but the short version is that this bitmap is basically a "super-bitmap" of a few bitmaps all adjacent to one another.
This 3728 size sucks. 1) It is not a power of two, and 2) prevents older video cards from having it in VRAM. Once the SDL rewrite, it is one of the first things that is going away.
Cheers!
Michael
> > The Color (Half-Shift) mode doesn't really do the half-shifting I'm
> > after. Are here any AppleWin developers around to ask for providing
> > such new video mode?
> >
> ...and the filtering is pretty complex compared to doing it once
> and saving the results in a table.
Great, but where is such a table? Does it already exist?
--
Linards Ticmanis
It's been a while, but IIRC someone(s?) wrote a DSP-like simulation of the
typical (not ideal) NTSC signal path and populated the table for all
possible 12-bit strings of "560" pixels.
Unfortunately, I can't put my finger on it at the moment.
-michael - NadaNet 3.1: http://home.comcast.net/~mjmahon
> Yeah, this has been a pet peeve of mine for a while now. I've
> implemented this tonight and uploaded a test version into the
> nightly build location.
Thanks, Michael. "Applewin.exe" from the nightly build location [1]
appears to do the half-shift but it appears no pure white is
displayed with it. I haven't got what the "Applewin_MonoVer1.exe"
version does but it doesn't appear to do the half-shifting.
[1] http://michael.peopleofhonoronly.com/dev/applewin/nightlybuild/
> I've also uploaded some raw HGR test images that you can load into
> the debugger as well.
>
> e.g.
> F2
> CTRL-F2
> HGR2
> F7
> bload "mono560.hgr",4000
> \
> F9 ...
> bload "gumball_machine.hgr",4000
> \
> F9 ...
>
> Note: The mono560 is the DOUBLE HI-RES from SILICON SALAD.
--
Stanimir
That was correct. I wanted to get something working.
I've put up new version. You can toggle the 4 monochrome half pixel modes!
The 75% mode was my personal favorite which was hard-coded in the version you just tried. You will probably like the new "Fake" mode.
Cheers
Michael
I've tried the new version, but something still doesn't feel quite
right. I'll be able to take a closer look after a week or so.
Thanks for putting this up.
--
Stanimir
Check nightly build.
I've moved all my monochrome test images into /nightlybuild/monochrome/ if anyone wants to play with this.
Cheers!
Michael
> It's been a while, but IIRC someone(s?) wrote a DSP-like simulation of the
> typical (not ideal) NTSC signal path and populated the table for all
> possible 12-bit strings of "560" pixels.
>
> Unfortunately, I can't put my finger on it at the moment.
Umm, perhaps something like this:
http://www.softjunk.org/sw/apple2/ra2/files/screenshot/ntsc/bpp/
It has the same example image rendered with 6, 9, 12 and 24-bit
vectors.
Marc Ressl has some great code which does not use tables at all.
> Alrighty then, Tom pointed out what I was still missing, so I've
> implemented a proper monochrome half-shift mode. It's dam close to
> the real thing now.
>
> Check nightly build.
Thanks, checked it out. Looks real close.
I think (while I can't remember for sure) the only thing missing is
the half-width pixel on the byte boundary with MSB set occurs only
when the neighbor byte doesn't have the MSB set. That is if the
boundary pixel and the MSB of a byte are set, and the next byte has
the MSB set, then the pixel is rendered half-shifted and full-width
(instead of half-width, always).
May be (but again, I'm not 100% sure) the only exception to the
previous rule is the pixel on the right screen boundary, which is
always rendered half-width if the MSB of the edge byte is set.
Following this line, the most-left screen pixel with MSB set should
be rendered pixel-and-a-half?
This I've come up while observing (and comparing to the feeling I've
got left from the past :-) ) the rendering of some games. I'm
trying with Gemstone Warrior, FWIW.
> I've moved all my monochrome test images into
> /nightlybuild/monochrome/ if anyone wants to play with this.
--
Stanimir
Feel free to give it a go.
Cheers
Michael
Yes, I remember something like that too.
This needs more testing so I can find test cases. I believe this is one...
Compare...
2000:7F 00
and
2000:7F 80
> May be (but again, I'm not 100% sure) the only exception to the
> previous rule is the pixel on the right screen boundary, which is
> always rendered half-width if the MSB of the edge byte is set.
> Following this line, the most-left screen pixel with MSB set should
> be rendered pixel-and-a-half?
More examples...
2800:80 D0 00
The right most pixel is half luminance.
Also
2027:70
2427:F0
The 2nd line is half-shifted, and cut off as expected.
2827:40
2C27:C0
Again, last dot is half luminance
Fun stuff !
Michael
> Ok, I've fixed a few edge cases.
>
> Feel free to give it a go.
Looks like real. :-)
It would be interesting to see the half-shifting combined with
color, too. Something like "Color (text optimized)" but preserving
the "geometry" of the "Mono Half Pixel Real".
I'll give it closer look when I get back, in a week. Thanks for
taking the time to implement this.
--
Stanimir
>> May be (but again, I'm not 100% sure) the only exception to the
>> previous rule is the pixel on the right screen boundary, which is
>> always rendered half-width if the MSB of the edge byte is set.
>> Following this line, the most-left screen pixel with MSB set should
>> be rendered pixel-and-a-half?
>
> More examples...
>
> 2800:80 D0 00
> The right most pixel is half luminance.
Thinking about it more, I think I've just made this in my mind. I
think it should just behave as the original rule, or may be better
stated - the right-most pixel is never rendered half-width.
> Also
> 2027:70
> 2427:F0
> The 2nd line is half-shifted, and cut off as expected.
>
> 2827:40
> 2C27:C0
> Again, last dot is half luminance
>
> Fun stuff !
--
Stanimir
But then there's no much choice with the fixed pixel resolution vs.
the extra margin to fit the half-shifted full-width pixel on the CRT
monitor. I think it is not worth the effort to compensate for that
(if I'm correct in my last comment at all).
--
Stanimir
I am running one of your recent nightly builds.
Here is a screenshot:
http://hoop-la.ca/apple2/2011/images/screenshot2011-01-08-at-6.52.13pm.png
Compare Mono Half Pixel Real in AppleWin to a partial screenshot from
Catakig which I was using in the summer. From what I can tell, the
half pixel shifting used in drawing the Lambda's look the same in both
emulators, except that Catakig is in color. I wish I had a real Apple
II to test with. Here is the program to draw a big Lambda using half
pixel shifting to get an effective resolution of 560 x 192 plus a few
artifacts...
9000 N = 95
9001 HGR : HCOLOR= 4
9002 FOR I = 1 TO 191 STEP 2
9003 HPLOT 0,I TO 279,I: NEXT
9004 D = 3
9005 S = N / D
9009 FOR I = 0 TO N
9010 HCOLOR= 3
9011 X = I + S
9012 Y = I * 2
9013 HPLOT I,Y TO X,Y
9015 IF I > = N / 2 THEN 9021
9016 Y = (N - I) * 2 + 1
9017 HPLOT I,Y TO X,Y
9021 Y = I * 2 + 1
9025 HCOLOR= 7
9027 HPLOT I,Y TO X,Y
9029 IF I > = N / 2 THEN 9040
9030 Y = (N - I) * 2
9031 HPLOT I,Y TO X,Y
9040 NEXT : VTAB 24
9050 POKE - 16302,0
I've updated the nightly build that fixes the monochrome text bug.
Monochrome Half-Pixel 75 looks the sharpest, but the most _accurate_ is Monochrome Half-Pixel Real, although the bottom left of the lambda is smooth in the Emulator. On my real //e in monochrome mode it is pretty jagged -- basically every other line in the bottom of the lamda is shifted over.
This is an awesome test image by the way. This is great to have something else to shoot for.
Cheers!
Michael
I agree! Maybe next weekend. Didn't realize I've basically spent all day working on this! Maybe I'll call it "Authentic Half-Shift Color" :-)
> I'll give it closer look when I get back, in a week. Thanks for
> taking the time to implement this.
No prob! It always bugged me that I couldn't run Silicon Salid DOUBLE HI-RES. The title of Archon looks great too!
Cheers
Michael
Yes, that's the comparison I mean.
> Marc Ressl has some great code which does not use tables at all.
It's hard to imagine a faster method than table lookup.
On modern CPUs' it is FAR faster to just calculate values then hit memory.
Upon further reflection, I'm not actually sure that's what I meant.
What I was referring to is the number of previous video bits that
are considered in arriving at the color of the current pixel. Since
all of his numbers are multiples of 3, he might be talking about RGB
color depth...I'm not sure which.
Agreed, that's why a 16KB table seemed about right. It would take
a lot of instructions to do the DSP work on the fly for two chroma
channels and the luminance channel.
It would be interesting to see the actual tradeoff for current
processors.
:-)
That's the proper Ying-Yang.
> What I was referring to is the number of previous video bits that
> are considered in arriving at the color of the current pixel. Since
> all of his numbers are multiples of 3, he might be talking about RGB
> color depth...I'm not sure which.
It's exactly the number of 14MHz pixels (samples) used to index a
table. Actually, 4 tables, because of the chroma phase. RGB value
(entry) is simple 32-bit, so table size is easy to calculate.
The length is odd for a certain obvious reason.
> Agreed, that's why a 16KB table seemed about right.
Direct table lookup needs 4x tables, which leaves us with 9-bit
vectors, which is around the bare minimum.
> It would take a lot of instructions to do the DSP work on the fly for two chroma
> channels and the luminance channel.
Yes and no.
Marc Ressl, optimizing further on the work of Blargg, came up with
solution that uses small tables that fit in L1 and is yet fast.
Most of all, it's obvious. :-)
I prefer to let Marc explain, since it's his study.
So would I! ;-)
I regret that I couldn't find the reference to his work.
-B
Compared to the standard...
http://michael.peopleofhonoronly.com/dev/applewin/nightlybuild/colorhalfpixel/u4_1_Std.bmp
The latest nightly build has proper color half-shift mode now ;-)
e.g.
HGR
CALL-151
2000:C4 00
2400:C4 80
2800:00 01
The first line has 2 pixels, the 2nd one is only half-width !
The second line has 2 pixels, the 2nd one is full-width, but shifted over half a pixel straddling a byte boundary!
The 3rd line is the first pixel column in the 2nd byte.
Cheers
Michael
You can see half a pixel in the blue water ...
i.e.
http://michael.peopleofhonoronly.com/dev/applewin/nightlybuild/colorhalfpixel/u4_5_Authentic.bmp
Right, but the half-blue pixel should be dark-blue since the resulting
pattern 0001 is identical to the corresponding 16-color pattern for
dark blue. Similarly, orange pixels cut in half are brown.
Still, though, great work!!!
-Brendan
>> It would be interesting to see the half-shifting combined with
>> color, too. Something like "Color (text optimized)" but preserving
>> the "geometry" of the "Mono Half Pixel Real".
>
> I agree! Maybe next weekend. Didn't realize I've basically
> spent all day working on this! Maybe I'll call it "Authentic
> Half-Shift Color" :-)
I've now tried it - it looks really nice.
--
Stanimir
> I remember on my Apple II clone (Pravetz 8C) using a monochrome monitor
> there was a graphics display behavior...
This seems like a good place to go ahead and announce that I have
shoved my NTSC video emulation code into Applewin. It's 90% complete
now. I do have a few things left to fix and I won't have much time for
the next week, so expect a release maybe in ~10 days.
Applewin developers: I have been brutal with the existing video code. I
haven't made any attempts to integrate with or play nice with the
existing code, I just #ifdef'd everything out that I didn't need.
All in all, I would rate the Applewin code as exceedingly ugly, but on
the other hand it seems to work well, which is more important.
I agree, although pockets of elegance exist.
> Applewin developers: I have been brutal with the existing video code. I
> haven't made any attempts to integrate with or play nice with the
> existing code, I just #ifdef'd everything out that I didn't need.
Now you know how your previous criticism arose. ;-)
The moral seems to be: Too many cooks eventually make broth that most
people like.
Cheers,
Nick.
Which also leads me to the wisdom I learned while traveling: If you
develop a liking for a particular restaurant, do yourself a favor and
don't ever look at what goes on in the kitchen.
-B
That's great!
Looking forward to reviewing your patch!
> All in all, I would rate the Applewin code as exceedingly ugly, but on
> the other hand it seems to work well, which is more important.
Was this your code or the existing AppleWin video code? I am going to assume you reffering to the existing AppleWin video code as being ugly?
Mike O'Brian, a game programmer who used to work at Blizzard, wrote the original video code. As a game programmer myself, I am going to go out on a (unpopular) limb here, disagree, and defend it a little (and that is even after implementing the proper half-pixel support!) :-)
It only appears convoluted because the elegance is not properly (or cleanly) documented. The original goal was to _minimize_ screen updates _and_ the amount of CPU work required to do so. In those 2 goals, it was beautifully written, and optimized.
Now I _will_ grant you, it looks fugly, for 2 main reason:
I. _how_ it is doing this is (was never?) documented.
II. tons of the hard-coded shifts for the address generation with ZERO plain reference implementation, the #define MACROS and consts don't exactly help with readability either.
e.g.
const int SRCOFFS_40COL = 0; // 0
const int SRCOFFS_IIPLUS = (SRCOFFS_40COL + 256); // 256
const int SRCOFFS_80COL = (SRCOFFS_IIPLUS + 256); // 512
const int SRCOFFS_LORES = (SRCOFFS_80COL + 128); // 640
const int SRCOFFS_HIRES = (SRCOFFS_LORES + 16); // 656
const int SRCOFFS_DHIRES = (SRCOFFS_HIRES + 512); // 1168
const int SRCOFFS_TOTAL = (SRCOFFS_DHIRES + 2560); // 3278
The first thing we run into is this Über 3278 x 512 bitmap called "source" in VideoInitialize().
To go into more detail into (I), there are 2 phases:
1. Über Bitmap Construction, Draw*Source(), that looks really strange
For all the possible Apple video modes, text, gr, dgr, hgr, dhgr we generate bitmaps. I'll give the pseudo-code for the HGR one, DrawHiResSource():
a) Here we break the screen up into 16 columns, this is the possible number of permutations for:
<second last bit of previous byte><last bit of previous byte><first bit of next byte><second bit of next byte>
b) Then we iterate all 256 byte values, transforming this 2+8+2 = 12 bit pixel
c) drawing a 32x2 bitmap into our uber bitmap.
The only "bug" I see, is that the "next" bits aren't used as far as I can tell. I suspect they "might" come into play with DHGR, but I haven't analyzed the code to know.
2. Copying partial bitmaps out of this Über sized bitmap.
a) All resolutions are broken up into 40x24 (40 columns and 24 rows)
b) Then we call a function pointer to update this "cell"
c) This pfUpdate then calls Update*Cell() to copy seven (7) 32x2 bitmaps into the framebuffer. e.g. UpdateHiResCell() Here we see the crap variable names:
byteval1
byteval2
byteval3
Really should be renamed:
nPrevByte
nThisByte
nNextByte
This is SO much readable. _Proper_ Variables names tell you _what_ the code is doing, comments tell you _why_. With proper variable names, you don't even need code half the time.
Going into (II) for more details, again using UpdateHiResCell() as an example:
while (yoffset < 0x2000)
yoffset += 0x400;
There really should be a comment:
// We process 8 scan lines at a time. These 8 scan lines are a constant $0400 apart.
// $2000 row 0
// $2400 row 1
// $2800 row 2
// $2C00 row 3
// $3000 row 4
// $3400 row 5
// $3800 row 6
// $3C00 row 7
// or
// $2080 row 8
// $2480 row 9
// $2880 row 10
// $2C80 row 11
// $3080 row 12
// $3480 row 13
// $3880 row 14
// $3C80 row 15
// etc.
// We bias the loop so that it starts at $0, instead of $2000, $2080, etc.
Again,
yoffset
Would be much clearer if we renamed it:
nHGRAddressStartScanLine
Hopefully this was enough to explain the AppleWin Video.cpp de-mystified. :-)
And yes, it will be nice when we eventually rip out all the "convoluted" original AppleWin video code and replace it with something more readable.
Cheers,
Michael - AppleWin Debugger Dev
Whoops, obviously should be: you don't even need _comments_ half the time.
:-)
It is typical of me to not include comments unless I think it does weird
stuff or is written in a bizarre way.
-uso.
>
>> All in all, I would rate the Applewin code as exceedingly ugly, but on>
>> the other hand it seems to work well, which is more important.
>
> Was this your code or the existing AppleWin video code? I am going to
> assume you reffering to the existing AppleWin video code as being ugly?
>
> Mike O'Brian, a game programmer who used to work at Blizzard, wrote the
> original video code. As a game programmer myself, I am going to go out
> on a (unpopular) limb here, disagree, and defend it a little (and that
> is even after implementing the proper half-pixel support!) :-)
Ok I'll backtrack and say it "appears" ugly. I endeavored to
understand the video code only to the degree that was necessary
to not remove what didn't need to go.
But I have to say I am not a fan of the way the CPU is implemented
either, although I'll grant that back in the 16-bit Windows days it
may have been necessary for speed.
I was also "shocked" by seeing the palettized bitmaps. It's been so
long since I've seen anything palettized I thought I was reading it
wrong at first (I'm not super familiar with Windows APIs).
> It only appears convoluted because the elegance is not properly (or
> cleanly) documented. The original goal was to _minimize_ screen
> updates _and_ the amount of CPU work required to do so. In those 2
> goals, it was beautifully written, and optimized.
>
> I. _how_ it is doing this is (was never?) documented.
> II. tons of the hard-coded shifts for the address generation with ZERO
> plain reference implementation, the #define MACROS and consts don't
> exactly help with readability either.
>
> e.g.
> const int SRCOFFS_40COL = 0; // 0
> const int SRCOFFS_IIPLUS = (SRCOFFS_40COL + 256); // 256
>
> The first thing we run into is this Über 3278 x 512 bitmap called
> "source" in VideoInitialize().
I had to figure out what this was because it wasn't clear to me
at first whether I wanted to use the "source" bitmap or the "frame"
bitmap. As it turns out, I basically use "frame", but a 32-bit-per-
pixel version of "frame".
> And yes, it will be nice when we eventually rip out all the
> "convoluted" original AppleWin video code and replace it with something
> more readable.
Well I don't know if my patch will make you want to do that or not.
It's not especially processor intensive on current systems, but
it requires more power than the old way.
The basic idea is to process the video data out of memory just like
a real Apple does, running it through some digital filters to
generate the RGB values to display, so all of that last pixel,
second to last pixel, stuff vanishes. It's just:
1) Based on video mode, call appropriate function (via pointer)
after every 6502 instruction.
2) Video function keeps track of video scanners (H & V), forms
video data address, reads memory and updates the offscreen
bitmap.
3) Copy the offscreen bitmap to the display occasionally.
The various functions for the video modes are almost identical,
but they differ in from where they get the data and how they
transform it before they shove it through the NTSC-emulation pixel
generator.
One last thing -- I downloaded Visual Studio 2010 express to work
on this, and it doesn't include the ddraw library, so I commented
that stuff out too. I don't know what will have to be done to make
my code work with it. (Maybe just a new target for bitblt?)
The CPU code is actually from the VICE emulator. AppleWin used to have
it's own CPU code, but we wanted to emulate the NMOS 6502's illegal
opcodes and decimal mode bugs. If you want to understand why we just
used VICE's code, read this:
http://www.viceteam.org/plain/64doc.txt
Cheers,
Nick.
..just as one who enjoys sausage should never see it being made. ;-)
Perhaps a separate 65C02 emulator would be much prettier...
Just wanted to say thanks for that cool link! Lots of Goodies in there!
Cheers
Michael
I agree, that there we are being pulled in 2 direction:
a) running on slower systems where we require fast emulation at the cost of accurate emulation. (supporting old Win98 systems that don't have much horespower), and
b) running on faster systems that enable us to do 100% proper emulation, albeit at a higher overhead -- maybe even using DirectX / pixel shaders ;-)
Regarding CPU usage, I've already mentioned this to Tom (and/or the other devs), and there are some things we could do to make this more "palatable", so to speak.
One more reason to join the AppleWin team so we don't have to (keep) re-posting discussions. :)
Cheers!
Michael