home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / WIN2VGA.ZIP / win2vga.txt
Internet Message Format  |  1994-11-18  |  27KB

  1. From slama@slama.pub.hr Fri Nov 18 20:23:46 1994
  2. From: slama@slama.pub.hr (Davor Slamnig)
  3. Newsgroups: comp.os.ms-windows.programmer.misc,rec.games.programmer
  4. Subject: From Windows to VGA mode 13h and back - summary w. demo (long)
  5. Date: Tue, 15 Nov 94 23:39:53 MET
  6. Organization: Disorganized
  7. Distribution: world
  8. NNTP-Posting-Host: srcapp.srce.hr
  9. Mime-Version: 1.0
  10. Content-Type: text/plain; charset=US-ASCII
  11. Content-Transfer-Encoding: 7bit
  12.  
  13.  
  14.     Hi
  15.  
  16.     This message contains a summary of posts and my personal
  17.     e-mail concerning the ways to stay in Windows and get
  18.     rid of the GDI. Specifically, the goal was to enter
  19.     VGA mode 13h, make direct writes to VGA RAM, and return
  20.     to Windows GDI.
  21.  
  22.     This way, you would have direct control over VGA RAM,
  23.     while still retaining the Windows memory management -
  24.     which means you can acces all the memory you have without
  25.     DOS-extenders (or Unix :)
  26.  
  27.     There are 3 ways to do it:
  28.  
  29.     1. Death / Resurrection                 (GDI.EXE)
  30.     2. DisableOEMLayer / EnableOEMLayer     (USER.EXE)
  31.     3. DisplayDib                           (DISPDIB.DLL)
  32.  
  33.     The first two function pairs are "undocumented" in
  34.     the sense that Microsoft doesn't mention them in manuals
  35.     and supposedly will not support them in future Windows
  36.     versions.
  37.  
  38.     DisplayDib is the only "supported" function, although
  39.     information about it is hard to find.
  40.  
  41.     This summary explains how to use all these functions
  42.     and how to get the VGA screen-start selector.
  43.     Thanks to all posters who unravelled the mystery
  44.     layer by layer (OEMLayer, too :)
  45.  
  46.     I should have posted this about 6 months earlier, when the
  47.     threads were active. But different cards displayed different
  48.     glitches, and I was not really sure whether they were caused
  49.     by DisplayDib or by other parts of my program(s).
  50.  
  51.     Anyway, I finaly wrote a bare-bones DisplayDib demo which
  52.     I'm appending to this text. The program enters DisplayDib
  53.     NOWAIT mode and then copies screen-sized buffers to VGA
  54.     RAM.
  55.  
  56.     I'm crossposting this to comp.os.ms-windows.programmer.misc
  57.     and rec.games.programmer because the original thread happened
  58.     in the windows conference, and the mechanism would be very
  59.     useful in game programming.
  60.  
  61. Slama
  62.  
  63. ----------------------------------------------------------------------
  64.  
  65. From: marnold@netcom.com (Matt Arnold)
  66. Subject: Re: How to call an undocumented Windows function?
  67.  
  68. slama@slama.pub.hr (Davor Slamnig) writes:
  69. >    How do I go about calling an undocumented Windows function?
  70. >    I found strings "DEATH" and "RESURRECTION" in gdi.exe (these
  71. >    functions shuld kill and restore Windows GDI).
  72. >    I tried to call them by name from BC++, but the linker can't
  73. >    find them.
  74.  
  75. That's cause IMPORT.LIB does not contain these "undocumented" functions
  76. for the linker to link with.
  77.  
  78. But you should be able to do it manually using...
  79.  
  80.    hGDI = GetModuleHandle("GDI");  // check on name here, "GDI" might be wrong
  81.    lpfnDeath = GetProcInstance(hGDI, "DEATH");
  82.  
  83.    lpfnDeath();   // call "DEATH" (takes parameters?)
  84.   
  85. ...for example. 
  86.  
  87. ---------------------------------------------------------------------------
  88.  
  89. From: "Philip K. Chung" <pkchung@phoenix.Princeton.EDU>
  90. Subject: Re: How to call an undocumented Windows function?
  91.  
  92. the follwing is taken directly out of _Undocumented_Windows_ by A.
  93. Schulman, D. Maxey, and M. Pietrek:
  94.  
  95. pp. 559-560
  96.  
  97. Death    GDI.121
  98.  
  99. void FAR PASCAL Death(HDC)
  100. HDC hDC; /* handle of desktop device context */
  101.  
  102. This function , called from the undocumented DisableOEMLayer function,
  103. disables the GDI display driver.  This returns the display  to the
  104. default text mode defined for the device, normally 80x25 in 16 colors.
  105.  
  106. Used by: USER.EXE
  107. Support: 3.0, 3.1
  108. See also: Resurrection, DisableOEMLayer, EnableOEMLayer
  109.  
  110. p. 589
  111.  
  112. Resurrection    GDI.122
  113.  
  114. void FAR PASCAL Resurrection(HDC, WORD, WORD, WORD, WORD, WORD, WORD)
  115. HDC hDC; /* Handle of desktop device context */
  116. WORD w1; /* unknown - set to 0 */
  117. WORD w2; /* unknown - set to 0 */
  118. WORD w3; /* unknown - set to 0 */
  119. WORD w4; /* unknown - set to 0 */
  120. WORD w5; /* unknown - set to 0 */
  121. WORD w6; /* unknown - set to 0 */
  122.  
  123. This function, called from the undocumented EnableOEMLayter function,
  124. enables the GDI graphics driver.  The driver in turn sets the display
  125. adapter to the active graphics mode for Windows.
  126.  
  127. Used by: USER.EXE
  128. Support: 3.0, 3.1
  129. See also: Death, DisableOEMLayer, EnableOEMLayer
  130.  
  131. hope this helps.  if you really want to get into these undocumented
  132. functions, you should definitely get this book.  it comes with some
  133. nifty utilities too.  actually even if you don't want to actually use
  134. these functions, it is probably a good book to take a look at.  it's
  135. about $40 i think.  the publisher is Addison-Wesley ISBN
  136. 0-201-60834-0.
  137.  
  138. ---------------------------------------------------------------
  139.  
  140. Subject: Re: How to call an undocumented Windows function? 
  141. From: Miguel Carrasquer <mcv@inter.nl.net>
  142.  
  143. I can tell you what Schulman c.s. say about these functions:
  144.  DisableOEMLayer disables the keyboard, mouse and display
  145. drivers, the system timer, and restores the previous video
  146. mode with a screen clear.  It calls the (non-exported) 
  147. InternalBroadcastDriverMessage, and also sends a notification
  148. to the network driver, if present.  You are left in "raw"
  149. DOS mode, but still in protected mode.
  150.  
  151. --------------------------------------------------------------------
  152.  
  153. From: "Scott C. Cottrille" <scottco@cs.washington.edu>
  154. Subject: Re: From Windows to VGA mode 13h and back
  155.  
  156. >From what I've been told, once you use Death(), you should be able to 
  157. directly write to VRAM.  However, you will have to use the exported 
  158. selector _A000h from KRNL386.EXE to get a pointer to VRAM (since you're 
  159. still in protected mode).  Try the following:
  160.  
  161.     extern WORD     _A000h;
  162.  
  163.     PBYTE        vidmem;
  164.     WORD        wTmp;
  165.  
  166.     wTmp = (WORD)(&_A000h);
  167.     vidmem = (PBYTE)MAKELP(wTmp, 0);
  168.         
  169. And in your .DEF file, under the imports section, add this line:
  170.  
  171.     __A000h = KERNEL.174
  172.  
  173. -----------------------------------------------------------------------
  174. Sender: "Pondor" <Pondor@aol.com>
  175. Subject: Re: How to call an undocumented Windows function?
  176.  
  177. >    I want to do direct to screen graphics under Windows.
  178. >    I manage to switch to VGA mode 13h (after killing GDI with
  179. >    DisableOEMLayer). But it seems that writing to absolute address
  180. >    0xa0000000 doesn't work in Windows.
  181. >    Any hints?
  182.  
  183. pp. 429-430
  184.  
  185. DisableOEMLayer   USER.4
  186.  
  187. void FAR PASCAL DisableOEMLayer(void);
  188.  
  189. This function disables the Windows OEM device interface.  It disables the
  190. keyboard, mouse and display drivers, and the system timer and restores the
  191. prior (probably non-graphics) video mode with a screen clear.  In addition,
  192. it uses an internal call, InternalBroadcastDriverMessage, to signal to all
  193. system drivers that the OEM layer is going down.  If there is a network
  194. driver present, it too is notified.  This effectively leaves the machine in
  195. "raw" DOS but still in protected mode.
  196.  
  197. See the discussion in EnableOEMLayer for more information.
  198.  
  199. Used by: WINOLDAP.MOD, WINOA286.MOD, but not WINOA386.MOD
  200. Support: 3.0, 3.1
  201. See also: EnableOEMLayer, and Death, Resurrection (Chapter 8)
  202. Example: See EnableOEMLayer
  203.  
  204. pp. 447-449
  205.  
  206. EnableOEMLayer   USER.3
  207.  
  208. void FAR PASCAL EnableOEMLayer(void);
  209.  
  210. This function enables the Windows OEM device interface, i.e. the interface
  211. between the Windows device independent API and BIOS and DOS device drivers.
  212.  While the OEM layer is disabled, access to devices is not available from the
  213. messaging interface; any application that disables the OEM layer must use
  214. traditional interrupts for console communication, for example.
  215.  
  216. When the OEM layer is reenabled, the screen is restored to graphics mode and
  217. the OEM layer takes over control of device management.  Specifically, the GDI
  218. layer is resurrected with a call to the undocumented Resurrection function,
  219. and then input from the mouse, keyboard, and system timer is reenabled.
  220.  System device drivers are notified that the OEM layer is coming up using a
  221. call to InternalBroadcastDriverMessage, (which is not exported).  If there is
  222. a network device driver, it too is notified.  Finally, the desktop is
  223. repainted; the message interface again becomes the means by which
  224. applications communicate with devices.
  225.  
  226. In real mode (Windows 3.0 only) and Windows standard mode, which runs in the
  227. 286 protected mode if the 80286/80386 processors, this is the means by which
  228. the Windows "Old App" (DOS) control application (WINOLDAP/WINOA286)
  229. disables/enables the Windows device layer to allow traditional DOS
  230. applications to run.
  231.  
  232. In 386 enhanced mode, where Windows runs in the V86 mode of the 80386
  233. processor, DOS applications run in separate virtual machines (VM) and can be
  234. "windowed" and preemptively multitasked.  In this mode, the control program
  235. (WINOA386) does not use Enable/DisableOEMLayer(), which do, however, still
  236. work.
  237.  
  238. Used by: WINOLDAP.MOD, WINOA286.MOD, but not WINOA386.MOD
  239. Support: 3.0, 3.1
  240. See also: DisableOEMLayer, and Death, Resurrection (chapter 8)
  241. Example: Uses DisableOEMLayer and EnableOEMLayer to switch into full screen
  242. text mode from within a Windows application.
  243.  
  244. /* OEMLAYER.C */
  245. #include <windows.h>
  246. #include <dos.h>
  247. #include "winio.h" // this in the accompanying disk
  248.  
  249. /* undocumented functions */
  250. extern void FAR PASCAL EnableOEMLayer(void);
  251. extern void FAR PASCAL DisableOEMLayer(void);
  252.  
  253. #include "checkord.c" // another file that comes with disk
  254.  
  255. void b800display(char *szDisplay)
  256.   {
  257.   unsigned lineofs = 0, chaarofs = 0, scrsel;
  258.  
  259.   printf("Screen Selector is %04x\n",
  260.   scrsel = (WORD)GetProcAddress(GetModuleHandle("KERNEL"), "__B800h"));
  261.  
  262.   for (; *szDisplay; szDisplay++)
  263.     switch (*szDisplay) {
  264.       case '\r' : charofs = 0; break;
  265.       case '\n' : lineofs += 160; break;
  266.       default :
  267.         *(WORD FAR *) MK_FP(scrsel, lineofs+charofs) = 
  268.                     0xe00 | *szDisplay;
  269.          charofs += 2;
  270.       }
  271.   }
  272.  
  273. int main()
  274.   {
  275.   // Ord/name check
  276.   if (! (CheckOrdName("EnableOEMLayer", "USER", 3)) &&
  277.           (CheckOrdName("DisableOEMLayer", "USER", 4)))
  278.     return 0;
  279.  
  280.   DisableOEMLayer();
  281.   b800display("\n"
  282.      "The OEM layer has been disabled, and normal Windows\r\n"
  283.      "keyboard and display handling have been suspended./\r\n"
  284.      "Direct writes to b800:0 are being used to display this,\r\n"
  285.      "and a call to Int 16h will be used to get your keystroke.\r\n"
  286.      "\r\n"
  287.      "Press a key to return.");
  288.  
  289.   _asm {
  290.      mov ah, 0
  291.      int 16h
  292.   }
  293.  
  294.   EnableOEMLayer();
  295.  
  296.   printf("\n\nProgram terminated.");
  297.  
  298.   return 0;
  299.   }
  300.  
  301. ---------------------------------------------------------------------
  302.  
  303. From: christb@infmuc (Christian Barmala)
  304. Subject: Re: Direct to video memory write under Windows
  305.  
  306. 1.    Use WinG
  307.  
  308. 2.    If you still want to access Video Memory be aware, that
  309.     you don't address SEGMENT:OFFSET, but SELECTOR:OFFSET.
  310.     You can create such a selector for instance with DPMI
  311.     services. Luckily  Windows 3.1 exports some predefined
  312.     selectors like "_C000" and guess what they map?
  313.  
  314. -----------------------------------------------------------------------
  315.  
  316. From: brent@aimla.com (Brent Burley)
  317. Subject: Re: Direct to video memory write under Windows
  318.  
  319. In article <2DqFqc1w165w@slama.pub.hr> slama@slama.pub.hr (Davor Slamnig) writes:
  320. |>        Well, I see that DISPDIB.DLL is in my \windows\system directory, and
  321. |>        that it contains two functions, DISPLAYDIBEX and DISPLAYDIB.
  322. |>        But BC++ 3.1 doesn't provide any information on their usage.
  323. |> 
  324. |>        Can anybody explain DISPLAYDIB in few precise words?
  325. |>        Or do I have to buy something?
  326.  
  327. DisplayDib is described in the Microsoft Windows Multimedia
  328. Programmer's Reference.  This is the only formal description I know
  329. of.  The Video for Windows SDK includes an updated DISPDIB.DLL and
  330. DISPDIB.H that have some enhancements that are not documented.  But
  331. it's all pretty easy to figure out.
  332.  
  333. If you have success with this, please post your experience.  I'd like
  334. more people to start using it so Microsoft will get the idea and
  335. document and promote it better.
  336.  
  337. I've included DISPDIB.H to give you an idea.
  338.  
  339. Here is the way that I call it:
  340.  
  341. BOOLEAN VgaSwitch(int on)
  342.     // on = 0:turn off, 1:turn on, -1: read state
  343. {
  344.     static BOOLEAN vgastatus = FALSE;
  345.     BOOLEAN prevstatus;
  346.     WORD flags;
  347.  
  348.     if (on == -1) return vgastatus;
  349.  
  350.     prevstatus = vgastatus;
  351.     if (on != vgastatus) {
  352.         if (on) flags = DISPLAYDIB_MODE_320x200x8 | DISPLAYDIB_BEGIN
  353. #ifdef DEBUG
  354.         // If you don't do this, the debugger won't be able to run
  355.         // But it's probably bad to leave it in production code
  356.          | DISPLAYDIB_DONTLOCKTASK
  357. #endif
  358.         ;
  359.         else flags = DISPLAYDIB_END | DISPLAYDIB_NOWAIT;
  360.         if (DisplayDib(NULL, NULL, flags)) {
  361.             MessageBox(NULL, "Can't switch to VGA mode", "", MB_ICONEXCLAMATION);
  362.             on = FALSE;
  363.         }
  364.         vgastatus = on;
  365.     }
  366.     return prevstatus;
  367. }
  368.  
  369. Init()
  370. {
  371.     ...
  372.  
  373.     WORD __A000H;
  374.  
  375.     VgaSwitch(1);
  376.     if (VgaSwitch(-1) == 0) return 0;
  377.  
  378.     // init physical display
  379. #define GET_SEL(name) \
  380.     ((WORD) (LOWORD(GetProcAddress(GetModuleHandle("KERNEL"), name))))
  381. #ifndef MK_FP // from dos.h
  382. #define MK_FP( seg,ofs )( (void _seg * )( seg ) +( void near * )( ofs ))
  383. #endif
  384.     __A000H = GET_SEL("__A000H");
  385.     Display.data = (unsigned char *) MK_FP(__A000H, 0);
  386.  
  387.     ...
  388. }
  389.  
  390. ---------------------------------------------------------------------------
  391.  
  392. From: brent@aimla.com (Brent Burley)
  393. Subject: Re: DisplayDib (VGA mode 13h in Windows)
  394.  
  395. In article <T0DJqc1w165w@slama.pub.hr>, slama@slama.pub.hr (Davor Slamnig) writes:
  396. |>     Question 1: Where does DisplayDib get the palette information
  397. |>     (if DISPLAYDIB_NOPALETTE is not set)? The BITMAPINFOHEADER struct
  398. |>     doesn't contain palette info:
  399.  
  400. If NOPALETTE is set, the palette is not set.  It could have been set with a
  401. previous call to DisplayDib or by using BIOS calls or writing to the palette
  402. registers directly.  Personally, I prefer to use the BIOS calls.
  403.  
  404. The initial state of the palette is undefined, though it may actually get the
  405. Windows system palette or the current Windows palette if it has one.  I'm not
  406. really sure - best to assume its unknown.
  407.  
  408. |>     Question 2: The DISPDIB.DLL supplied in DISPDIB.EXE is smaller
  409. |>     (4400 bytes) than the one I have on my system (5744 bytes). It contains
  410. |>     just the DisplayDib function, and "my" DLL has DisplayDibEx, too.
  411. |>     What does DisplayDibEx do?
  412.  
  413. The one I use I got from the Video for Windows SDK.  It is 7168 bytes and is
  414. dated 11/19/93.  It seems to do a better job recovering from program
  415. exceptions and critical errors that previous versions.
  416.  
  417. DisplayDibEx allows you to blit an image at an X,Y offset.  Thus you can do
  418. sprite like things.  But I don't use it since I write directly to video
  419. memory.
  420.  
  421. |>     Question 3: Where can I get comprehensive information concerning
  422. |>     DISPDIB.DLL functions? Could somebody post and/or e-mail it to me?
  423.  
  424. There is a short description in the Multimedia Programmer's Reference.  There
  425. is also a mention in the article "Animation in Windows" on the Developer's
  426. Library CD.  I've heard rumor that it will be documented in the next WinG
  427. release.  But the best source of info is the header file and experimentation.
  428.  
  429. Some tips:
  430. 1) Make sure you have a mono monitor for debugging.
  431. 2) Set the DONT_LOCK_TASK flag in your debug versions.
  432. 3) Call Yield() before DisplayDib() if you want to switch to VGA at the
  433. beginning of your program.  Otherwise you won't get mouse input.  And don't
  434. ask me why.
  435. 4) Use the exported variable __A0000 to access the VGA frame buffer.
  436.  
  437. ------------------------------------------------------------------------
  438.  
  439. From: brent@aimla.com (Brent Burley)
  440. Subject: Re: Direct to video memory write under Windows
  441.  
  442. In article <2gsgqc1w165w@slama.pub.hr>, slama@slama.pub.hr (Davor Slamnig) writes:
  443. |> brent@aimla.com (Brent Burley) writes:
  444. |> 
  445. |>     If Chicago supports DisplayDib, and doesn't include Death and
  446. |>     Resurrection, then DisplayDib is rewritten to use two new
  447. |>     undocumented Chicago functions.
  448.  
  449. A guy from Microsoft told me that they have reworked DisplayDib
  450. considerably to get it to work properly under Chicago and that
  451. Death/Resurrection will no longer be available.
  452.  
  453. I have also been told by someone who has the Chicago beta that
  454. DisplayDib still works fine.
  455.  
  456. Summary:  Death/Resurrection are undocumented - all bets are off.
  457. DisplayDib _is_ documented and will continue to be available in
  458. Chicago.
  459.  
  460. --------------------------------------------------------------------
  461.  
  462. From: scottco@lynx.cs.washington.edu (Scott C. Cottrille)
  463. Subject: Re: Direct to video memory write under Windows
  464.  
  465. Davor Slamnig (slama@slama.pub.hr) wrote:
  466. : brent@aimla.com (Brent Burley) writes:
  467.  
  468. : > Death/Resurrection to use mode 13h in Windows is a BAD thing.
  469. : > Use DisplayDib().  This is reliable, supported, works on all
  470. : > systems, and will work under Chicago.  Death/Resurrection is
  471. : > not/does not/will not.
  472. : > 
  473. : > DisplayDib is used by Microsoft for Video for Windows.  It is
  474. : > also recommended by Microsoft as the _only_ way to switch to 
  475. : > Mode X and write to video memory from Windows.
  476.  
  477. :     Since I have no info on the usage of DisplayDib, I disassembled
  478. :     parts of DISPDIB.DLL. And guess what - it uses Death and
  479. :     Resurrection. So it can't be more reliable than them.
  480.  
  481. :     If Chicago supports DisplayDib, and doesn't include Death and
  482. :     Resurrection, then DisplayDib is rewritten to use two new
  483. :     undocumented Chicago functions.
  484.  
  485. :     Here are two excerpts from DISPDIB.DLL. Notice the characteristic 6
  486. :     zero args to Resurrection:
  487. :  ...
  488. :   cs:0344 50             push   ax
  489. :   cs:0345 8BF8           mov    di,ax                        
  490. :   cs:0347 9A67206F04     call   046F:2067       ;Death
  491. :  ...
  492. :   cs:04C3 50             push   ax                           
  493. :   cs:04C4 6A00           push   0000                         
  494. :   cs:04C6 6A00           push   0000                         
  495. :   cs:04C8 6A00           push   0000                         
  496. :   cs:04CA 6A00           push   0000                         
  497. :   cs:04CC 6A00           push   0000                         
  498. :   cs:04CE 6A00           push   0000                         
  499. :   cs:04D0 8BF0           mov    si,ax                        
  500. :   cs:04D2 9A8E206F04     call   046F:208E       ;Resurrection
  501. :  ...
  502.  
  503. :     Still, I'd like to have some information on DisplayDib and DisplayDibEx
  504. :     usage. An exact pointer to a ftp site, filenames & paths would be nice,
  505. :     or better yet some posted/mailed info. The DisplayDib args, at least.
  506.  
  507. : Slama
  508.  
  509. try ftp.microsoft.com, \Softlib\MSLFILES\dispdib.exe.  There is a header file
  510. that prototypes DisplayDib (but not DisplayDibEx, but I don't know what else
  511. you'd need).  The header file is not real verbose, but you can glean the
  512. information you want from it. 
  513.  
  514. -------------------------------------------------------------------------
  515.  
  516. /****************************************************************************/
  517. /*                                                                          */
  518. /*        DISPDIB.H - Include file for DisplayDib() function.               */
  519. /*                                                                          */
  520. /*        Note: You must include WINDOWS.H before including this file.      */
  521. /*                                                                          */
  522. /*        Copyright (c) 1990-1993, Microsoft Corp.  All rights reserved.    */
  523. /*                                                                          */
  524. /****************************************************************************/
  525.  
  526. // DisplayDib() error return codes
  527. #define DISPLAYDIB_NOERROR          0x0000  // success
  528. #define DISPLAYDIB_NOTSUPPORTED     0x0001  // function not supported
  529. #define DISPLAYDIB_INVALIDDIB       0x0002  // null or invalid DIB header
  530. #define DISPLAYDIB_INVALIDFORMAT    0x0003  // invalid DIB format
  531. #define DISPLAYDIB_INVALIDTASK      0x0004  // not called from current task
  532.  
  533. // flags for <wFlags> parameter of DisplayDib()
  534. #define DISPLAYDIB_NOPALETTE        0x0010  // don't set palette
  535. #define DISPLAYDIB_NOCENTER         0x0020  // don't center image
  536. #define DISPLAYDIB_NOWAIT           0x0040  // don't wait before returning
  537. #define DISPLAYDIB_NOIMAGE          0x0080  // don't draw image
  538. #define DISPLAYDIB_ZOOM2            0x0100  // stretch by 2
  539. #define DISPLAYDIB_DONTLOCKTASK     0x0200  // don't lock current task
  540. #define DISPLAYDIB_TEST             0x0400  // testing the command
  541. #define DISPLAYDIB_NOFLIP           0x0800  // dont page flip
  542. #define DISPLAYDIB_BEGIN            0x8000  // start of multiple calls
  543. #define DISPLAYDIB_END              0x4000  // end of multiple calls
  544.  
  545. #define DISPLAYDIB_MODE             0x000F  // mask for display mode
  546. #define DISPLAYDIB_MODE_DEFAULT     0x0000  // default display mode
  547. #define DISPLAYDIB_MODE_320x200x8   0x0001  // 320-by-200
  548. #define DISPLAYDIB_MODE_320x240x8   0x0005  // 320-by-240
  549.  
  550. // function prototypes
  551. #ifdef __cplusplus
  552. extern "C" {
  553. #endif
  554. UINT FAR PASCAL DisplayDib(LPBITMAPINFOHEADER lpbi, LPSTR lpBits, WORD wFlags);
  555. UINT FAR PASCAL DisplayDibEx(LPBITMAPINFOHEADER lpbi, int x, int y, LPSTR lpBits, WORD wFlags);
  556. #ifdef __cplusplus
  557. }
  558. #endif
  559.  
  560. #define DisplayDibBegin() DisplayDib(NULL, NULL, DISPLAYDIB_BEGIN)
  561. #define DisplayDibEnd()   DisplayDib(NULL, NULL, DISPLAYDIB_END)
  562.  
  563. --------------------------------------------------------------------------
  564.  
  565. /*
  566.    ddib.c
  567.  
  568.    DisplayDib demo
  569.    Davor Slamnig (slama@lama.pub.hr)
  570.    11/94
  571.  
  572.    Gets screen address selector from kernel, enters DisplayDib
  573.    NOWAIT mode, copies prepared buffer to screen memory.
  574.    On keypress returns to Windows GUI.
  575.  
  576.    BC++ 3.1, large model
  577.  
  578.    Create DISPDIB.LIB import library for
  579.    WINDOWS\SYSTEM\DISPDIB.DLL using the Import lib utility.
  580.    Add DISPDIB.LIB to project.
  581. */
  582.  
  583. #if !defined(__COMPACT__)
  584. # if !defined(__LARGE__)
  585. #  if !defined(__HUGE__)
  586. #   error Large data model required.
  587. #  endif
  588. # endif
  589. #endif
  590.  
  591. #include <windows.h>
  592. #include "dispdib.h"
  593. //#include <stdio.h>
  594. #include <string.h>
  595. #include <stdlib.h>
  596.  
  597. #define BALL_W    8
  598. #define YLEN      18
  599.  
  600. char szAppName[] = "DisplayDib";
  601. HWND Hwnd;
  602. char Str[1000];
  603. unsigned char *W_a000h;
  604. unsigned char *Back_buf;
  605. unsigned char Ball[] = {
  606.    0, 0, 9, 9, 9, 9, 0, 0,
  607.    0, 9, 9, 9, 9, 9, 9, 0,
  608.    9, 9,11, 9, 9, 9, 9, 9,
  609.    9, 9, 9, 9, 9, 9, 1, 9,
  610.    9, 9, 9, 9, 9, 9, 1, 9,
  611.    9, 9, 9, 9, 9, 1, 1, 9,
  612.    0, 9, 9, 1, 1, 1, 9, 0,
  613.    0, 0, 9, 9, 9, 9, 0, 0,
  614. };
  615. int Y[YLEN] = {
  616.    20, 21, 23, 26, 30, 35, 41, 48, 56, 65,
  617.    75, 86, 98, 111, 126, 142, 159, 177
  618. };
  619.  
  620. BITMAPINFOHEADER Bmih;
  621. int Bouncing = 0;
  622.  
  623. void put_sprite(int x, int y, int w, int h, unsigned char *bmap)
  624. {
  625.    unsigned char *dest;
  626.  
  627.    for(dest = Back_buf + y * 320 + x;
  628.       h > 0;
  629.       --h, bmap += w, dest += 320)
  630.  
  631.       memcpy(dest, bmap, w);
  632. }
  633.  
  634. void bounce_loop(void)
  635. {
  636.    int x = 0, ydx = 0, xdir = 1, ydir = 1;
  637.    MSG msg;
  638.  
  639.    while(Bouncing){
  640.       memset(Back_buf, 0, 64000U);
  641.       put_sprite(x, Y[ydx], BALL_W, BALL_W, Ball);
  642.       memcpy(W_a000h, Back_buf, 64000U);
  643.  
  644.       if(x >= 319 - BALL_W)
  645.          xdir = -4;
  646.       else if(x <= 0)
  647.          xdir = 4;
  648.  
  649.       if(ydx >= YLEN - 1)
  650.          ydir = -1;
  651.       else if(ydx <= 0)
  652.          ydir = 1;
  653.  
  654.       x += xdir;
  655.       ydx += ydir;
  656.  
  657.       if(PeekMessage(&msg, Hwnd, 0, 0xffff, PM_REMOVE)){
  658.          TranslateMessage(&msg);
  659.          DispatchMessage(&msg);
  660.       }
  661.    }
  662. }
  663.  
  664. void WVGA_init(void)
  665. {
  666.    unsigned scrsel;
  667.    HMODULE hKERNEL;
  668.    char KERNELname[200];
  669.  
  670.    hKERNEL = GetModuleHandle("KERNEL");
  671.    GetModuleFileName(hKERNEL, KERNELname, 200);
  672.    scrsel = (unsigned)GetProcAddress(hKERNEL, "__A000h");
  673.    W_a000h = (unsigned char *)MAKELP(scrsel, 0);
  674. }
  675.  
  676. void start_ddib(void)
  677. {
  678.    size_t size;
  679.  
  680.    memset(&Bmih, 0, size = sizeof(BITMAPINFOHEADER));
  681.  
  682.    Bmih.biSize = size;
  683.    Bmih.biPlanes = 1;
  684.    Bmih.biBitCount = 8;
  685.    Bmih.biCompression = BI_RGB;
  686.  
  687.    DisplayDib(&Bmih, NULL,
  688.                DISPLAYDIB_NOPALETTE |
  689.                DISPLAYDIB_NOCENTER |
  690.                DISPLAYDIB_NOWAIT |
  691.                DISPLAYDIB_BEGIN |
  692.                DISPLAYDIB_MODE_320x200x8);
  693. }
  694.  
  695. void end_ddib(void)
  696. {
  697.    DisplayDib(&Bmih, NULL, DISPLAYDIB_NOWAIT | DISPLAYDIB_END);
  698. }
  699.  
  700. long FAR PASCAL _export WndProc (HWND hwnd, UINT message, UINT wParam,
  701.                                                           LONG lParam)
  702. {
  703.    HDC hdc;
  704.    PAINTSTRUCT ps;
  705.    RECT rect;
  706.  
  707.    switch(message){
  708.    case WM_CREATE:
  709.       WVGA_init();
  710.       if((Back_buf = (unsigned char*)malloc(64000U)) == NULL){
  711.          MessageBox(NULL, "Can't alloc background buffer", "DDIB",
  712.             MB_OK);
  713.          PostMessage(Hwnd, WM_DESTROY, NULL, NULL);
  714.       }
  715.       break;
  716.    case WM_KEYDOWN:
  717.       if(!Bouncing){
  718.          Bouncing = 1;
  719.          start_ddib();
  720.          bounce_loop();
  721.       }
  722.       else{
  723.          Bouncing = 0;
  724.          end_ddib();
  725.       }
  726.       return 0;
  727.    case WM_KILLFOCUS:
  728.    case WM_SYSKEYDOWN:
  729.       if(Bouncing){
  730.          Bouncing = 0;
  731.          end_ddib();
  732.          return 0;
  733.       }
  734.       break;
  735.    case WM_PAINT:
  736.       if(!Bouncing){
  737.          hdc = BeginPaint (hwnd, &ps);
  738.          SetBkMode(hdc, TRANSPARENT);
  739.          SetTextColor(hdc, RGB(255, 255, 255));
  740.          GetClientRect (hwnd, &rect);
  741.          DrawText (hdc,
  742.          "\n\nDisplayDib Test\n\n\nDavor Slamnig, 11/94\
  743. \n\nPress any key to start...",
  744.          -1, &rect, DT_CENTER);
  745.          EndPaint (hwnd, &ps);
  746.       }
  747.       return 0;
  748.    case WM_DESTROY:
  749.       PostQuitMessage(0);
  750.       return 0 ;
  751.    }
  752.  
  753.    return DefWindowProc (hwnd, message, wParam, lParam) ;
  754. }
  755.  
  756. int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance,
  757.                     LPSTR lpszCmdParam, int nCmdShow)
  758. {
  759.    MSG msg;
  760.    WNDCLASS wndclass;
  761.  
  762.    if(hPrevInstance)
  763.       return msg.wParam;
  764.  
  765.    wndclass.style = CS_HREDRAW | CS_VREDRAW;
  766.    wndclass.lpfnWndProc = WndProc;
  767.    wndclass.cbClsExtra = 0;
  768.    wndclass.cbWndExtra = 0;
  769.    wndclass.hInstance = hInstance;
  770.    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  771.    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  772.    wndclass.hbrBackground = GetStockObject(BLACK_BRUSH);
  773.    wndclass.lpszMenuName = NULL;
  774.    wndclass.lpszClassName = szAppName;
  775.  
  776.    RegisterClass (&wndclass);
  777.  
  778.    Hwnd = CreateWindow(szAppName, szAppName, WS_OVERLAPPEDWINDOW,
  779.             CW_USEDEFAULT, CW_USEDEFAULT, 460, 200, NULL, NULL,
  780.             hInstance, NULL);
  781.  
  782.    ShowWindow(Hwnd, nCmdShow);
  783.    UpdateWindow(Hwnd);
  784.  
  785.    while(GetMessage(&msg, NULL, 0, 0)){
  786.       TranslateMessage(&msg);
  787.       DispatchMessage(&msg);
  788.    }
  789.  
  790.    return msg.wParam;
  791. }
  792.  
  793. -------------------------- end of code -------------------------
  794.  
  795.  
  796.  
  797.