how cards.dll works
jonwil at tpgi.com.au
Mon Jul 28 06:53:12 CDT 2003
After finding out that certain things I did when coding cards.dll (such as
studying the complete code in a disassembler) mean that any code I write
for it a potential "derivitave work", I have come up with a descrition that
is (hopefully) detailed enough to enable someone else with windows GDI
programming experience to write cards.dll for wine but (hopefully) not
detailed enough to be considered a "derivitive work"
The folowing files can be made available to whoever ends up working on
1.cards.spec, a ready made spec file for the dll
2.cards.rc, a RC file containing the card bitmaps (which are licenced under
a licence that gave permission to use them) and also the card back bitmaps
that were sent to me before (to whoever ends up working on this, feel free
to modify the images if you dont like them :)
3.makefile.in ready made for the dll
and 4.cards.h which contains the publicly documented interface to cards.dll
(which I pulled from various info documents found on the net)
IANAL but I dont think that any of these could be claimed to be covered by
that "derivitave work" thing, if they are, please do tell me.
This document explains the workings of cards.dll (version 5.00.2134.1 from
windows XP SP1)
Cards.dll exports 7 different functions.
cdtInit takes 2 int * variables. It should return TRUE if the initalization
was sucessfull and FALSE if it was not.
It is a place to do any initalization you require (depending on for example
if you want to preload the resource bitmaps or whatever).
It should return the x and y size of the card bitmaps in the 2 variables.
For the cards I am using, the x size is 71 and the y size is 96 (which just
happened to match up with the size of microsofts cards which is good)
the main purpose of DllMain is to store the HINSTANCE of the cards.dll to
use later when the bitmaps are loaded
WEP is a holdover from when cards.dll was a 16 bit dll and doesnt actually
need to be implemented (since its never called by 32 bit windows)
cdtTerm is where you undo anything you did in cdtInit (such as unloading
any preloaded resources)
It takes no parameters and returns nothing.
cdtAnimate is supposed to handle animations for the card backs but since
the backs we are using dont animate, it can just return TRUE
(hence why the resource file I wrote returns the windows XP version number
since XP doesnt have animated backs either)
As for parameters, it takes a HDC, an x and y position and a frame number
(each individual microsoft back has a specific number of frames and
applictions tend to hard-code these values)
cdtDraw basicly calls cdtDrawExt passing the default size of the card
bitmaps as the x and y size parameters
The real work is done in cdtDrawExt
This function takes:
a HDC (for the screen window to draw the card on)
an X positon and a Y position to draw the card at
a card number (cards.h lists the different values)
a mode number (again cards.h lists the different values)
and a RGB background color
What the function does depends on the value of the mode.
If the upper bit of md (which is an int) is set, then it shouldnt save and
resore the corner pixels (as explained below)
modes greater than 7 should (as far as I can tell) do nothing.
mode 0 is "draw face card"
mode 1 is "draw back"
mode 2 is "draw highlighted face card"
mode 3 is "draw empty card spot"
mode 4 is "erase card"
mode 5 is "draw empty card spot but doesnt paint background"
mode 6 is "draw red X card"
and mode 7 is "draw green O card"
all modes use the same "drawing logic" except for mode 4 which doesnt draw
You need a resource ID and a raster OP to do the drawing
For modes 0 and 2, the resource ID uses this formula
resource id equals ((((card number shl 2) mod 0dh) plus ((card number and
3) times 0dh)) plus 1)
For mode 1, the resource ID is just the card number
For modes 3 and 5, the resource ID is 53 (the resource ID of the empty card
spot graphic, also the contant hb in cards.h)
For mode 1, the resource ID is just the card number
For mode 6, the resource ID is 67 (the resource ID of the card with the red
X on a green background graphic, also the contant xb in cards.h)
For mode 7, the resource ID is 68 (the resource ID of the card with the
green O on a green background graphic, also the contant ob in cards.h)
and mode 4 doesnt use any ID since it doesnt draw anything.
For the raster OP, all modes use SRCCOPY except for:
mode 2 which uses NOTSRCCOPY
and modes 3 and 5 which use SRCAND
Also, if the mode is 0, the background color is set to white (0xFFFFFF)
before drawing. And after drawing, if the card is a red card (resource IDs
0x0E to ox17 and 0x1B to 0x24), it paints over the boarders of the card
using PatBlt and the BLACKNESS rasterop.
If the mode is 3 or 4, it creates a solid brush using the background color,
uses SetBrushOrgEx to set the brush origin to the screen DC origin and then
uses PatBlt to paint over the area of the card using PATCOPY.
If the mode has the top bit clear (as explained above) and the size matches
with the default card size, before drawing, it saves the corner pixels of
the cards (the card bitmaps I am using have one pixel in each corner) and
then restore them after drawing.
To do the actual drawing, you need to load the bitmap resource into memory
and load the resulting HBITMAP into a memory DC.
You also need to set the background color of the screen DC to whatever was
passed in (unless its mode 0, in which case its 0xFFFFFF as explained
above). And then, you need to copy the data from the memory DC to the
screen DC using either BitBlt or StretchBlt as appropriate.
Remeber to free all the GDI resources (bitmaps, memory DCs etc) that you used.
And also to restore the background color to whatever it was
before you changed it.
If the function is a sucess, you return TRUE.
If the function is a failure (e.g. a GDI function call fails), you return
Hoepfully someone can use this information to implement cards.dll in a way
that is legally safe.
More information about the wine-devel