home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!mcsun!Germany.EU.net!unido!sbsvax!aldebaran!winter
- From: winter@cs.uni-sb.de (Stefan Winterstein)
- Newsgroups: comp.sys.amiga.programmer
- Subject: Upside-down graphics revisited
- Keywords: Kopfstand, hack, upside-down, negative modulo
- Message-ID: <20782@sbsvax.cs.uni-sb.de>
- Date: 17 Aug 92 08:39:40 GMT
- References: <1992Aug4.171235.19277@doug.cae.wisc.edu>
- Sender: news@sbsvax.cs.uni-sb.de
- Reply-To: winter@cs.uni-sb.de
- Followup-To: Upside down graphics??
- Organization: Universitaet des Saarlandes
- Lines: 222
-
-
- In article <1992Aug4.171235.19277@doug.cae.wisc.edu>
- pochanay@cae.wisc.edu (Adisak Pochanayon) asked:
- >
- > Can anyone tell me if the hardware BitPlane Mod values are signed or
- >unsigned? If they are signed, it should be extremely easy to display
- >a graphic screen upside down. Has anyone tried this? If so, is it
- >possible to do under 1.3 and 2.0 using the graphics.library functions
- >on a viewport?
-
- Yes - there really IS such a thing as a negative modulo.
- Yes - this can be used to turn the display upside down - without
- blitting tons of BitPlane data.
- And Yes - this can be done in a completely system-friendly (well, sort
- of OS-supported) manner: Ever used a *negative* Bitplane width?
-
- Appended is the commented SAS/C source of my program 'Kopfstand'
- ("head-stand"?), which simply turns the frontmost screen upside-down.
- This can be Workbench or any other screen you like. Everything continues
- to work just fine, except the screen is turned.
- Mouse pointer and movement are not mirrored, you have to guess the
- position on the original screen. You exit the program by holding down
- the mouse button for about one second. (You can use LALT-LAMIGA to
- simulate a mouse click without exiting Kopfstand.)
-
- Here is a quick explanation of how it works: First, 'Kopfstand' makes
- a copy of the BitMap structure belonging to the frontmost screen, which it
- modifies in two ways:
- - by calling InitBitMap with *negative* Screen width
- - by making the plane pointers point to *last* row of their plane
-
- It then attaches this BitMap to the current ViewPort's BitMap pointer
- (while leaving the Screen's BitMap alone) and lets graphics.library
- recalculate the appropriate copperlist. Et voila` - we have our negative
- modulo, which equals -2*ScreenWidth.
- Since we changed the plane pointers, the last line of the plane is the
- first line on the screen. Add the negative modulo and the next line
- displayed is the last-but-first line of the plane and so on (prove of
- correctness by induction on BitMap->Rows...).
-
- Warning: This program does one nasty thing or two. Especially
- changing plane pointers in the current ViewPort's BitMap is not a
- very safe thing to do (but since the usual way to get plane pointers is
- from the Screen's BitMap, it usually works). Also 'Kopfstand' relies on
- the fact that the screen turned upside-down will not close before turned
- back again.
- After all, this is a screen hack in the truest of sense - use it at
- your own risk. Don't blame me if your Amiga gurus, formats your
- hard-drive or blows up your house (although I didn't encounter anything of
- the above ;-))
-
- 'Kopfstand' is dedicated to Leo L. Schwab.
-
- Any reaction on this article is welcome. Enjoy!
-
- -Stefan
-
- P.S.: I posted it in c.s.a.programmer since c.s.a.sources seems to be
- rather unreliable.
- --- ///
- Stefan Winterstein, Schwarzbachstr. 7, W-6650 Homburg 6, Germany ///
- Usenet: winter@cs.uni-sb.de __ ///
- SGNTR VRS VRSN 3.1B: \\\ ///
- Strppd nd cmprssd fr qckr trnsmssn. nfct yrs tdy! \\X//
-
-
- -------- cut here -------- Kopfstand.c -------- cut here --------
- ;/* Execute me to compile !
- lc -cfist -j73 -ms -M -O -rr -v -w Kopfstand.c
- blink Kopfstand.o SC SD ND
- quit
- */
- /*********************************************************************/
- /* */
- /* Kopfstand.c */
- /* ~~~~~~~~~~~ */
- /* by Stefan Winterstein */
- /* (winter@cs.uni-sb.de) */
- /* */
- /* Makes topmost Screen stand upside-down. */
- /* */
- /* Exit by pressing LMB for a while. */
- /* */
- /* Neither uses Blitter nor moves BitPlanes about in memory. */
- /* */
- /* Ever heard of negative plane width and modulo??? Look and see! */
- /* */
- /* Dedicated to Leo L. Schwab */
- /* */
- /* Written 16-Aug-92 using SAS/C 5.10b */
- /* */
- /*********************************************************************/
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <hardware/cia.h>
- #include <graphics/view.h>
- #include <intuition/intuitionbase.h>
-
- #define _USEOLDEXEC_
- #include <proto/dos.h>
- #include <proto/exec.h>
- #include <proto/graphics.h>
- #include <proto/intuition.h>
-
- #define CHECKDELAY 50L
- #define ciaa (*((struct CIA *) 0xbfe001))
-
- void __stdargs __saveds
- main(void) /* entry point */
- {
- struct DosLibrary *DOSBase;
- struct GfxBase *GfxBase;
- struct IntuitionBase *IntuitionBase;
-
- struct View *v;
- struct ViewPort *vp;
- struct Screen *s;
- struct BitMap *realbm, *mybm;
-
- UWORD height, bpr, planedelta, width, depth, i;
-
-
- if (IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 33L)) {
- if (GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 33L)) {
- if (DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 33L)) {
- if (mybm = AllocMem(sizeof(*mybm), MEMF_PUBLIC | MEMF_CLEAR)) {
-
- Forbid(); /* Nobody should disturb us. */
-
- /* First we need to know a few addresses: */
- v = ViewAddress(); /* Intuition's View, */
- s = IntuitionBase->FirstScreen; /* the top-most Screen */
- vp = &(s->ViewPort); /* and its ViewPort. */
-
- /*
- * Now look for the BitMap structure
- */
- realbm = &s->BitMap;
-
- /* and make a copy of it. */
- *mybm = *realbm;
-
- /* The following values are needed later */
- depth = mybm->Depth;
- height = mybm->Rows;
- bpr = mybm->BytesPerRow;
- width = bpr << 3;
-
- /* This is the byte offset for the last line of a plane. */
- planedelta = bpr * (height-1);
-
- /*
- * Here comes the trick:
- *
- * We call InitBitMap() with a *negative* width!
- * When we supply the ViewPort with our faked BitMap
- * to MakeVPort(), graphics.library will
- * construct a copperlist with the appropriate
- * negative modulo values for BPLxMOD.
- */
- InitBitMap(mybm, depth, -width, height);
-
- /*
- * We want the last line of a plane to be the
- * first line on the display, so we'll have to
- * make eache plane pointer point to the last line
- * of the plane, which is planedelta bytes away.
- */
- for (i=depth; i; )
- mybm->Planes[--i] += planedelta;
-
- /*
- * Now we patch in the faked BitMap into the ViewPort.
- * The Screen's BitMap is not changed, so that all
- * graphic output continues to go to the right place.
- */
- vp->RasInfo->BitMap = mybm;
-
- /* let graphics.library build that crazy copperlist */
- MakeVPort(v, vp);
- MrgCop(v);
-
- /* and load it. */
- LoadView(v);
-
- /* Voil`! */
-
- /*
- * We leave our faked BitMap in our ViewPort for
- * a little longer so that every time Intuition builds up a
- * new copperlist (e.g. ScreenToFront), it is fooled
- * and displays our ViewPort upside-down.
- * Lets hope nobody closes it in the meantime...
- */
-
- Permit();
-
- /* Now check for a mouse click every once in a while. */
- while ((ciaa.ciapra) & (1 << CIAB_GAMEPORT0))
- Delay(CHECKDELAY);
- /* (dirty, I know...) */
-
- /* We are done now, restore the original BitMap, */
- vp->RasInfo->BitMap = realbm;
- /* (even dirtier...) */
-
- /* and reach normality. */
- MakeVPort(v, vp);
- MrgCop(v);
- LoadView(v);
-
- FreeMem(mybm, sizeof(*mybm));
- }
- CloseLibrary ((struct Library *) DOSBase);
- }
- CloseLibrary ((struct Library *) GfxBase);
- }
- CloseLibrary ((struct Library *) IntuitionBase);
- }
- }
- -------- cut here -------- Kopfstand.c -------- cut here --------
-