Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

AppleWin Video Mode: Monochrome (Half-Shift)

105 views
Skip to first unread message

Stanimir Stamenkov

unread,
Jan 2, 2011, 8:36:31 AM1/2/11
to
I remember on my Apple II clone (Pravetz 8C) using a monochrome
monitor there was a graphics display behavior used in programs and
games which allowed to display smoother letters and shapes like
(ASCII-art, use monospace font):

** ** 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

sicklittlemonkey

unread,
Jan 2, 2011, 7:09:52 PM1/2/11
to

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.

BLuRry

unread,
Jan 2, 2011, 8:01:40 PM1/2/11
to

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

Michael J. Mahon

unread,
Jan 3, 2011, 1:10:54 AM1/3/11
to

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."

Stanimir Stamenkov

unread,
Jan 3, 2011, 4:30:33 PM1/3/11
to
Sun, 02 Jan 2011 22:10:54 -0800, /Michael J. Mahon/:

> BLuRry wrote:
>
>> 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. ;-)
>
> That's the kind of implementation I would have expected, and
> it should deliver the "half-pixel" shift the OP is looking for.

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

TomCh

unread,
Jan 3, 2011, 6:12:59 PM1/3/11
to

Michael J. Mahon

unread,
Jan 4, 2011, 1:17:29 AM1/4/11
to

That's correct--and it gives rise to some peculiar "dark" colors
in color mode.

Michael AppleWin Debugger

unread,
Jan 4, 2011, 10:32:28 AM1/4/11
to
Nick / Blurry, can you send that code over please?

Thanks

Michael AppleWin Debugger

unread,
Jan 4, 2011, 10:34:38 AM1/4/11
to
Now that I have my Apple Color Monitor, I've been motivated to slowl grok this code and fix the dam debugger colors in full screen mode.

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

BLuRry

unread,
Jan 4, 2011, 12:23:07 PM1/4/11
to
On Jan 4, 9:32 am, Michael AppleWin Debugger

<michael.pohore...@gmail.com> wrote:
> Nick / Blurry, can you send that code over please?
>
> Thanks

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)

http://java-ace.svn.sourceforge.net/viewvc/java-ace/jace/src/jace/apple2e/VideoDHGR.java?revision=108&view=markup

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

Michael J. Mahon

unread,
Jan 4, 2011, 3:27:05 PM1/4/11
to

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...

Michael AppleWin Debugger

unread,
Jan 4, 2011, 5:07:55 PM1/4/11
to
> 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

Michael J. Mahon

unread,
Jan 5, 2011, 12:25:50 AM1/5/11
to

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.

Michael AppleWin Debugger

unread,
Jan 5, 2011, 2:28:45 PM1/5/11
to
You wouldn't happen to have any links/docs for this NTSC work by chance?


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

sicklittlemonkey

unread,
Jan 5, 2011, 8:14:26 PM1/5/11
to
On Jan 6, 8:28 am, Michael AppleWin Debugger

<michael.pohore...@gmail.com> wrote:
> You wouldn't happen to have any links/docs for this NTSC work by chance?

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.

Michael J. Mahon

unread,
Jan 6, 2011, 12:43:32 AM1/6/11
to

...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.

Michael AppleWin Debugger

unread,
Jan 6, 2011, 11:29:46 AM1/6/11
to
Thanks Nick

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

Michael J. Mahon

unread,
Jan 6, 2011, 3:02:48 PM1/6/11
to
Michael J. Mahon wrote:
> sicklittlemonkey wrote:
>
>> On Jan 6, 8:28 am, Michael AppleWin Debugger
>> <michael.pohore...@gmail.com> wrote:
>>
>>> You wouldn't happen to have any links/docs for this NTSC work by chance?
>>
>>
>>
>> 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).
>
>
> ...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 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.

Michael AppleWin Debugger

unread,
Jan 7, 2011, 4:58:06 AM1/7/11
to
Hi Stanimir,

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?
> >

Linards Ticmanis

unread,
Jan 7, 2011, 7:57:07 AM1/7/11
to
On 01/06/2011 06:43 AM, Michael J. Mahon wrote:

> ...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

Michael J. Mahon

unread,
Jan 7, 2011, 6:26:34 PM1/7/11
to

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

Stanimir Stamenkov

unread,
Jan 7, 2011, 7:57:10 PM1/7/11
to
Fri, 7 Jan 2011 01:58:06 -0800 (PST), /Michael AppleWin Debugger/:

> 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

Michael AppleWin Debugger

unread,
Jan 7, 2011, 10:37:52 PM1/7/11
to
> appears to do the half-shift but it appears no pure white is
displayed with it.

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

Stanimir Stamenkov

unread,
Jan 8, 2011, 7:19:27 AM1/8/11
to
Fri, 7 Jan 2011 19:37:52 -0800 (PST), /Michael AppleWin Debugger/:

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

Michael AppleWin Debugger

unread,
Jan 8, 2011, 4:43:54 PM1/8/11
to
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.

I've moved all my monochrome test images into /nightlybuild/monochrome/ if anyone wants to play with this.

Cheers!
Michael

vladitx

unread,
Jan 8, 2011, 5:22:35 PM1/8/11
to
On Jan 8, 1:26 am, Michael J. Mahon <mjma...@aol.com> wrote:

> 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.

Stanimir Stamenkov

unread,
Jan 8, 2011, 6:18:24 PM1/8/11
to
Sat, 8 Jan 2011 13:43:54 -0800 (PST), /Michael AppleWin Debugger/:

> 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

Michael AppleWin Debugger

unread,
Jan 8, 2011, 7:50:01 PM1/8/11
to
Ok, I've fixed a few edge cases.

Feel free to give it a go.

Cheers
Michael

Michael AppleWin Debugger

unread,
Jan 8, 2011, 8:03:43 PM1/8/11
to
> 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).

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

Stanimir Stamenkov

unread,
Jan 8, 2011, 8:47:48 PM1/8/11
to
/Michael AppleWin Debugger/:

> 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

Stanimir Stamenkov

unread,
Jan 8, 2011, 8:50:24 PM1/8/11
to
/Michael AppleWin Debugger/:

>> 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

Stanimir Stamenkov

unread,
Jan 8, 2011, 9:25:09 PM1/8/11
to
Sun, 09 Jan 2011 03:50:24 +0200, /Stanimir Stamenkov/:

> /Michael AppleWin Debugger/:
>
>>> 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.

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

mmphosis

unread,
Jan 8, 2011, 10:07:26 PM1/8/11
to
Looking good. :)

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

Michael AppleWin Debugger

unread,
Jan 9, 2011, 12:12:19 AM1/9/11
to
Thanks,

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

Michael AppleWin Debugger

unread,
Jan 9, 2011, 12:14:49 AM1/9/11
to
> 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'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

Michael J. Mahon

unread,
Jan 9, 2011, 5:02:41 AM1/9/11
to
vladitx <vla...@nucleusys.com> wrote:
> On Jan 8, 1:26 am, Michael J. Mahon <mjma...@aol.com> wrote:
>
>> 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.

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.

Michael AppleWin Debugger

unread,
Jan 9, 2011, 11:45:07 AM1/9/11
to
Depends how large the table is (how well it maps to the L1/L2 cache)

On modern CPUs' it is FAR faster to just calculate values then hit memory.

Michael J. Mahon

unread,
Jan 9, 2011, 3:44:19 PM1/9/11
to
Michael J. Mahon wrote:
> vladitx <vla...@nucleusys.com> wrote:
>
>>On Jan 8, 1:26 am, Michael J. Mahon <mjma...@aol.com> wrote:
>>
>>
>>>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.
>
>
> Yes, that's the comparison I mean.

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.

Michael J. Mahon

unread,
Jan 9, 2011, 3:47:38 PM1/9/11
to
Michael AppleWin Debugger wrote:
> Depends how large the table is (how well it maps to the L1/L2 cache)
>
> On modern CPUs' it is FAR faster to just calculate values then hit memory.

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.

vladitx

unread,
Jan 9, 2011, 6:10:09 PM1/9/11
to
On Jan 9, 10:44 pm, "Michael J. Mahon" <mjma...@aol.com> wrote:
> > Yes, that's the comparison I mean.
>
> Upon further reflection, I'm not actually sure that's what I meant.

:-)

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.

vladitx

unread,
Jan 9, 2011, 6:16:57 PM1/9/11
to
On Jan 9, 10:47 pm, "Michael J. Mahon" <mjma...@aol.com> wrote:

> 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.

Michael J. Mahon

unread,
Jan 9, 2011, 8:34:40 PM1/9/11
to

So would I! ;-)

I regret that I couldn't find the reference to his work.

BLuRry

unread,
Jan 10, 2011, 3:56:49 PM1/10/11
to
Ultimately, Hires can be blitted as a Double-hires screen and then rendered as such. That was my experience with the whole thing. The half-pixel oddness happens with the hi-bit changes and there is a pixel on the right-edge and the pixel gets chopped in half. If you treat it as such, you can use your routines which output double hi-res color as needed. Two birds with one stone, basically. If your double-hires output looks accurate then so will your hires output since they follow the same rules at the end of the day. Sorry if this is redundant and AppleWin already does this -- I'm not too familiar with the code.

-B

Michael AppleWin Debugger

unread,
Jan 11, 2011, 2:35:31 AM1/11/11
to
You mean like this ... ? :-)
http://michael.peopleofhonoronly.com/dev/applewin/nightlybuild/colorhalfpixel/u4_5_Authentic.bmp

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

Michael AppleWin Debugger

unread,
Jan 12, 2011, 12:44:21 PM1/12/11
to
Yup, AppleWin now does this. :-) Note, haven't bothered with the double hi-res stuff.

You can see half a pixel in the blue water ...
i.e.
http://michael.peopleofhonoronly.com/dev/applewin/nightlybuild/colorhalfpixel/u4_5_Authentic.bmp

BLuRry

unread,
Jan 12, 2011, 1:22:58 PM1/12/11
to
On Jan 12, 11:44 am, Michael AppleWin Debugger

<michael.pohore...@gmail.com> wrote:
> Yup, AppleWin now does this. :-)   Note, haven't bothered with the double hi-res stuff.
>
> You can see half a pixel in the blue water ...
> i.e.http://michael.peopleofhonoronly.com/dev/applewin/nightlybuild/colorh...

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

Stanimir Stamenkov

unread,
Jan 23, 2011, 5:56:26 PM1/23/11
to
Sat, 8 Jan 2011 21:14:49 -0800 (PST), /Michael AppleWin Debugger/:

>> 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

Sheldon Simms

unread,
Feb 5, 2011, 2:33:34 PM2/5/11
to
On 2011-01-02 08:36:31 -0500, Stanimir Stamenkov said:

> 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.

sicklittlemonkey

unread,
Feb 5, 2011, 4:23:30 PM2/5/11
to
On Feb 6, 8:33 am, Sheldon Simms <wsspa...@gmail.com> wrote:
> 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.

BLuRry

unread,
Feb 6, 2011, 10:27:17 AM2/6/11
to

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

Michael AppleWin Debugger

unread,
Feb 6, 2011, 11:31:05 AM2/6/11
to
> 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.

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

Michael AppleWin Debugger

unread,
Feb 6, 2011, 1:09:17 PM2/6/11
to
> 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.

Whoops, obviously should be: you don't even need _comments_ half the time.

:-)

Steve Nickolas

unread,
Feb 6, 2011, 5:26:53 PM2/6/11
to

It is typical of me to not include comments unless I think it does weird
stuff or is written in a bizarre way.

-uso.

Sheldon Simms

unread,
Feb 6, 2011, 11:35:29 PM2/6/11
to
On 2011-02-06 11:31:05 -0500, Michael AppleWin Debugger said:

>
>> 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?)

sicklittlemonkey

unread,
Feb 7, 2011, 12:01:20 AM2/7/11
to
On Feb 7, 5:35 pm, Sheldon Simms <wsspa...@gmail.com> wrote:
> 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.

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.

Michael J. Mahon

unread,
Feb 7, 2011, 3:48:35 PM2/7/11
to

..just as one who enjoys sausage should never see it being made. ;-)

Michael J. Mahon

unread,
Feb 7, 2011, 3:51:12 PM2/7/11
to

Perhaps a separate 65C02 emulator would be much prettier...

Michael AppleWin Debugger Dev

unread,
Feb 15, 2011, 2:18:10 PM2/15/11
to
Nick,

Just wanted to say thanks for that cool link! Lots of Goodies in there!

Cheers
Michael

Michael AppleWin Debugger Dev

unread,
Feb 15, 2011, 2:30:41 PM2/15/11
to
> 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.

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

0 new messages