
Why was Pinball removed from Windows Vista? - pavel_lishin
http://blogs.msdn.com/b/oldnewthing/archive/2012/12/18/10378851.aspx
======
shmageggy
The best part of this article is in the comments. An original programmer on
the game explains the reason that the bug was occurring and also why the code
was unreadable (hint: they did it in assembly)

 _Ah, the quantum tunneling pinball!

We ran into this while writing the original code at Cinematronics in 1994.
Since the ball motion, physics, and coordinates were all in floating point,
and the ball is constantly being pushed "down" the sloped table by the gravity
vector in every frame, we found that floating point error would gradually
accumulate until the ball's position was suddenly on the other side of the
barrier!

(To simplify collision detection, the ball was reduced to a single
point/vector and all barriers were inflated by the ball radius. So, if the
mathematical point got too "close" to the mathematical line barrier, a tiny
amount of floating point rounding or truncation error could push the point to
the other side of the line)

To mitigate that, we added a tiny amount of extra bounce to push the ball away
from the barrier when it was nearly at rest, to keep the floating point error
accumulation at bay. This became known as the Brownian Motion solution.

Since much of the original code was written in x86 asm to hand tailor Pentium
U/V pipelines and interleave FPU instructions, but wiki says Microsoft ported
the code to C for non-Intel platforms, I'm sure the code had passed through
many hands by the time it got to you. The Brownian Motion solution may have
been refactored into oblivion._

[http://blogs.msdn.com/b/oldnewthing/archive/2012/12/18/10378...](http://blogs.msdn.com/b/oldnewthing/archive/2012/12/18/10378851.aspx#10379160)

~~~
Evgeny
I'm so happy you posted that - otherwise I would not read down more than a
couple first comments and would miss this!

~~~
shmageggy
My procrastination from studying for finals says "you're welcome"

------
randomdrake
This is an excellent example of why comments in code are so very useful,
helpful and in my opinion, necessary.

 _... nobody at Microsoft ever understood how the code worked (much less still
understood it), and that most of the code was completely uncommented, we
simply couldn't figure out why the collision detector was not working. Heck,
we couldn't even find the collision detector!_

To all those folks out there who keep finding reasons to try and be clever
with their language, or omit comments from their code: now you can remember
Pinball. It's very possible that with some minimal commenting about what
functions did, or what the intentions of block of codes were, Pinball could
have lived on. Heck, we could have even seen a Modern UI version of Pinball.

~~~
mikeash
It's an argument for clear code that's readily understandable by other people.
It's not an argument for any particular technique for achieving that goal.
I've never seen any programmer seriously suggest that code should be
deliberately made difficult to understand.

~~~
h2s
I can't agree with you emphatically enough about this. Cargo cult commenting
is one of the easiest ways to damage the readability of a codebase.

Comments should be an edge-case solution for explaining unusual quirks, not
the go-to approach for explaining the entire codebase. Using comments to
explain what the code is up to is like using exceptions for flow of control. A
large proportion of the comments I see should actually be function or method
names for a more well factored version of the block of code that follows.

~~~
RegEx
This point gets brought up a lot, but I'm not going to complain at all. In
fact, just 5-6 months ago I used to be one of those programmers who would do

    
    
        # gets the xml
        def get_xml():
    
    

It took comments like this to help me realize just how silly the whole thing
was. Now I write as much self-documenting code as I can, but comment as
needed.

~~~
Funnnny
Sure.

Comment should be "why I did this", and code should be "how I did this", some
people just write in "what did I do" and walk away thought they have comment

Code took from a project I'm working with:

    
    
      #End of package

~~~
StavrosK
I generally become aware that I should leave a comment whenever I write
something that is less than trivial (but exactly less than trivial) to
write/understand. Longish list comprehension? Summarize what it does. Nested
function calls? Summarize why. Etc.

------
streptomycin
Too bad it wasn't open source, then someone would have fixed it for free.

~~~
MatthewPhillips
Someone asked that in the comments, and he responded that it was licensed from
a 3rd party company.

~~~
ben0x539
Take the argument a step further: Microsoft "should" have required the 3rd
party to provide the code under an open-source license.

~~~
Firehed
Open source wasn't exactly a huge priority for Microsoft in 1995 when the
application came into existence. In fact I think it's a testament to their
backwards compatibility that pinball survived for as long as it did with
little or no maintenance.

~~~
rbanffy
Quite the opposite. In 1995, killing open source was one of Microsoft's top
priorities. It isn't much lower on the list these days.

~~~
Luyt
Indeed, and it was still on their agenda in 1998. Microsoft saw Linux as their
worst enemy and developed business strategies to eradicate it (by means of
'de-commoditizing'). Then, the 'Halloween Documents' leaked. ESR writes:

 _"In the last week of October 1998, a confidential Microsoft memorandum on
Redmond's strategy against Linux and Open Source software was leaked to me by
a source who shall remain nameless."_ This document can be read at
<http://www.catb.org/esr/halloween/halloween1.html>

Read more at <http://www.catb.org/esr/halloween/>

------
barbs
Apparently, you can just copy the folder across to an installation of the
later versions of windows and it's "fully functional"

<http://mspinball.weebly.com/>

I can't try this right now, since I don't currently have access to a Windows
machine, but can anyone confirm/deny this? Do you get the floating-point
gravity bug?

~~~
shrikant
I'm on 32-bit Windows 7, and it works fine. The plunger is a little sluggish
to respond, but otherwise no sign of the gravity bug!

~~~
StavrosK
64-bit Ubuntu works fine, too. The ball disappears in some frames, but it's no
thing.

------
tolos
argh

> The source code was licensed from another company. If you want the source
> code, you have to go ask them.

Twice this mystery company is referenced, but never a name is mentioned.

~~~
bunderbunder
Google to the rescue!

<http://en.wikipedia.org/wiki/Full_Tilt!_Pinball>

------
moepstar
Heh, 's nice to read about that and as a pinball-enthusiast i'm a bit saddened
for it to be gone, even if it is more for retro-reasons as opposed to it being
special in some way...

Maybe MS should team up with someone who understands making (digital)
pinballs, like the guys that created Zen Pinball?

------
cjensen
To me, the lesson is: _Do not duplicate code!_ and _keep it simple stupid_

When implementing Unicode, MS said "hey let's copy all of our API functions to
new names". Now they have two problems.

When implementing 64-bit, MS said "hey let's have a completely different OS
for 64-bit." Now they have four problems.

Compare this to Unix/Linux/MacOS where Unicode is just implemented as a
standard way (UTF-8) of encoding characters into the existing API. And there
need only be one shipping OS which supports both 32-bit and 64-bit process
types equally since there are only a handful of kernel APIs compared to
thousands for Windows.

~~~
ww520
Confusing the Linux kernel service API and the OS API is pretty misleading.

~~~
cjensen
Nope. Windows does not distinguish between a kernel APIs versus other APIs.
They are all "The Win{32,64} API"

~~~
ww520
Again, you are confused with user mode API (Win32/64) and kernel mode service
API. Windows does have kernel mode service API. Just it's not well known since
most people don't need to deal with them.

------
zaroth
Apparently, someone has actually FIXED it and put it online. Although hard to
know if the linked EXE isn't just a trojan. Anyone have a clean room they can
test it in?

<http://mspinball.weebly.com/index.html>

See:
[http://blogs.msdn.com/b/oldnewthing/archive/2012/12/18/10378...](http://blogs.msdn.com/b/oldnewthing/archive/2012/12/18/10378851.aspx#10379299)

------
crescentfresh
Wait, can't 64-bit windows run 32-bit programs?

~~~
missing_cipher
Answer is in the article:

[That would have been even more work, because there was at the time no
infrastructure in Setup for having 32-bit-only components. (And then
automatically uninstalling it when WOW64 was disabled.) And besides, all the
people who criticized Windows 96 as "not really a 32-bit operating system
because it has some parts in 16-bit" would use the same logic to say that
64-bit Windows is "not really a 64-bit operating system." -Raymond]

~~~
chimeracoder
Man, if that's the case, does using a BIOS mean I'm still running a 16-bit
operating system?

If so, then I guess I've got to marvel at how popular "16-bit" Linux is - I
can run 64-bit only applications, watch Flash, Netflix... whoever knew a
16-bit OS could be so powerful!

------
robomartin
> nobody at Microsoft ever understood how the code worked (much less still
> understood it), and that most of the code was completely uncommented, we
> simply couldn't figure out why the collision detector was not working. Heck,
> we couldn't even find the collision detector!

This continues to be one of my pet peeves, particularly with code samples and
a lot of what is posted on Github, even major libraries. Almost no comments,
background or guidance on the intent and structure or the code.

No, I am not suggesting that something like this is necessary:

    
    
        // Iterate through all elements 
        for(int i=0; i < count; i++
        {
            // Check that velocity isn't above threshold
            if(velocity[i] > THRESHOLD)
            {
             // Limit velocity
             velocity[i] = THRESHOLD;
             ...
    

That's ridiculous. However, something like this is useful:

    
    
        // Bounds-check velocities
        for(int i=0; i < count; i++
        {
            if(velocity[i] > THRESHOLD)
            {
             velocity[i] = THRESHOLD;
             ...
    

Anyhow, dumb example I pulled out of thin air.

I've heard some say "I just write self-documenting code". That's a myth but
for the simplest of structures. Any non-trivial piece of work is far from
being self-documenting. Code is self-documenting for the guy who wrote it. I
guarantee you that anyone else reading it has to reconstruct a stack in their
head to understand what the hell is going on. That's not self-documentation. I
shouldn't have to think to understand what a chunk-o-code is doing. The same
for functions and/or methods.

The myth of self-documenting code is easy to demonstrate if I show you a piece
of code in a language you don't know. I am going to assume that most
programmers these days don't know assembler, Forth or Lisp.

    
    
        (defun GetPolylineEndEntities ( plename / plends cvcenter cvsize oldcmdecho pt1 pt2 endss outlist)
            (setq plends (GetPolylineEnds plename))
            (setq cvcenter (getvar "viewctr")
                cvsize   (getvar "viewsize")
                oldcmdecho (getvar "CMDECHO")
            )    
            (setvar "CMDECHO" 0)
    
            (foreach point plends
             (progn
                (setq pt1 (add2d point '(-0.0125 -0.0125)))
                (setq pt2 (add2d pt1 '(0.025 0.025)))
                (command "zoom" "c" point 2)
                (setq endss (ssdel plename (ssget "C" pt2 pt1)))
                (setq outlist (append outlist (list (ssname endss 0))))
             )
            )
            (command "zoom" "c" cvcenter cvsize)
            (setvar "CMDECHO" oldcmdecho)
            outlist
        )
    

I wrote this twenty years ago. Even if you understand Lisp you'd have to think
it through. However, this is not how I wrote it. This is what I actually
wrote:

    
    
        ;=====================================================================================================
        ; GetPolylineEndEntities
        ;
        ; Argument: Polyline entity name
        ; Return: Two element list containing the first (if any) entity found at the end of the polyline.
        ;         The polyline itself is excluded.
        ;         If nothing is found at a particular end, that element in the list is set to nil.
        ;
        (defun GetPolylineEndEntities ( plename / plends cvcenter cvsize oldcmdecho pt1 pt2 endss outlist)
            (setq plends (GetPolylineEnds plename))    ;Get the endpoints
    
            (setq cvcenter (getvar "viewctr")
                cvsize   (getvar "viewsize")
                oldcmdecho (getvar "CMDECHO")
            )    
            (setvar "CMDECHO" 0)
    
            (foreach point plends
             (progn
                ;Examine what connects at each end
                (setq pt1 (add2d point '(-0.0125 -0.0125)))
                (setq pt2 (add2d pt1 '(0.025 0.025)))
    
                ;Zoom to the end being analyzed to have better selection accuracy
                ; **** Have to figure out a way to do this without zooming ****
                (command "zoom" "c" point 2)
            
                ;Eliminate the original cable from the resulting selection set
                (setq endss (ssdel plename (ssget "C" pt2 pt1)))
    
                ;Add the first entity found to the output list
                (setq outlist (append outlist (list (ssname endss 0))))
             )
            )
            (command "zoom" "c" cvcenter cvsize)
            (setvar "CMDECHO" oldcmdecho)
            outlist
        )
    

Even if you don't know Lisp you now have an idea of what this code is doing.
My style has changed over the years. This isn't my best example, but it is
here to drive a point home.

The use of an unfamiliar language serves to illustrate the point that the idea
of self-documenting code is, again, a myth. I wrote that code myself and
without the comments I'd have to mentally reconstruct every step to even begin
to understand what's going on and what the intent was. I haven't touched Lisp
in quite some time.

I've looked through so much code in Github without a single comment that it
makes me wonder if this is what is being taught in schools these days.
Accurate in-code documentation is, as far as I am concerned, part and parcel
of becoming a professional programmer. It recognizes that the work represents
a huge investment in time, money and intellectual effort and it ensures that
this effort and expense doesn't have to be duplicated in order to maintain,
evolve or migrate the product as the Microsoft example clearly demonstrates.

~~~
yxhuvud
>That's ridiculous. However, something like this is useful:

> // Bounds-check velocities

No, that is an example of a comment of a region that should have been a
separate method/function.

~~~
robomartin
Not really.

If you throw methods and functions at everything all you are doing is adding
the processing overhead of the entry and exit from the method or function.
These are not magical entities. There's a time, a place and cost to using
them.

Having come up from assembly and, in general, low level coding, one becomes
very aware of what is being created behind the scenes. Unless something like
this contrived bounds-check test will be used multiple times across a module
or modules there's no reason whatsoever to add the overhead of entering and
exiting a function for a simple couple of if/else-if/else statements.

I see this all the time. Everything has to be an object and everything has to
be a class with a pile of properties and methods. No it doesn't. Massive
projects --critical projects-- have been done over the years without any of
that. Be careful not to engage in creating a monument to a coding paradigm
rather than a tight, fast, practical and sensible solution to a problem.

~~~
yxhuvud
Then tell your compiler to inline it - but don't bother doing it until you
have measured it to actually have a measureable impact. Readability and
rewriteability dominate that kind of unguided microoptimizations you seem to
like all the time.

That doesn't mean to abstract for the sake of abstraction but to choose the
right abstraction. Writing code so that it is easy to reach the right
abstraction helps a lot.

------
shmerl
They should include Xbill by default:

<http://xbill.org>

------
zwieback
I have a virtual machine running XP for testing installers of internal tools
(many engineers at HP are still running XP).

Just played a round of pinball. Despite having used Windows since 2.0, I
didn't even know Pinball existed before.

------
Wingman4l7
Another good comment that's buried near the bottom, written by one of the
authors of the game, regarding the ownership of the code:
[http://blogs.msdn.com/b/oldnewthing/archive/2012/12/18/10378...](http://blogs.msdn.com/b/oldnewthing/archive/2012/12/18/10378851.aspx#10379245)

------
jfreak53
Ahh gotta love Wine! Runs everything :) <http://i.imgur.com/ekhiY.jpg>

What ever you do DO NOT press F4 for fullscreen, it botches dual-monitors on
Gnome. Took me 20 min. to get back up and running again.

BUT, Pinball works :)

------
isabre
I used to play Pinball at school whenever I was in the Computer Lab. I also
spent the bulk of my time in the computer lab at recess. Brings back old
memories.

------
AndreyKarpov
Perhaps it would help to quickly find bugs -
<http://www.viva64.com/en/viva64-tool/> :)

------
forgotAgain
So now we know how insecure XP was (is).

