home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************\
- * KeyBang *
- * ------- *
- * by Mike Stark *
- * Revisions: *
- * 1.0 30 Mar 92 Added patterns, removed floating point math, added intro *
- * window, improved input handler and added command options. *
- * 0.9 23 Feb 92 Added the input handler so that keybanging would get the key *
- * events before intuition. *
- * 0.8 Made PAL/NTSC independent. *
- * 0.7 Added the ability to play random sounds. *
- * 0.? Original version (Shapes in response to intuition events) *
- * Credits: *
- * Michael Balzer (balzer@heike.informatik.uni-dortmund.de), the author of *
- * "Bomber" for a C example of how to use the audio device. *
- * Carolyn Scheppner of CATS for "OneKey" which is a concise example of how *
- * to install and use an input handler. *
- \******************************************************************************/
-
- #include "KeyBang.h"
- #include "table.h"
-
- char *version = "\0$VER: KeyBang 1.0 by Mike Stark (March 30, 1992)";
-
- #define VECTORS 30
- #define CLOCK 3579545
- #define FORM 0x464f524d
- #define BODY 0x424f4459
- #define VHDR 0x56484452
- #define EIGHT_SVX 0x38535658
- #define SOUNDDIRNAME "Sounds:"
-
- extern void BabyInputHandler();
-
- SHORT ColorTable[16] =
- {
- 0x0000, 0x0eca, 0x0c00, 0x0f60, 0x0090, 0x03f1, 0x000f, 0x02cd, 0x0f0c,
- 0x0a0f, 0x0950, 0x0fe0, 0x0fff, 0x0ccc, 0x0888, 0x0444
- };
-
- #define PATTERNS 6
-
- USHORT PatternData[] =
- {
- /* Solid */
- 0xffff,
- /* Brick */
- 0x0101, 0x0101, 0x0101, 0xff01, 0x0101, 0x0101, 0x0101, 0x01ff,
- /* Grid */
- 0xffff, 0x0303, 0x0303, 0x0303,
- /* Diagonal lines */
- 0xf0f0, 0x3c3c, 0x0f0f, 0xc3c3,
- /* Other diagonal lines */
- 0x0f0f, 0x3c3c, 0xf0f0, 0xc3c3,
- /* Other brick pattern */
- 0x0300, 0x0300, 0x0300, 0xffff, 0x0003, 0x0003, 0x0003, 0xffff
- };
-
- struct PatternInfo
- {
- int Power;
- USHORT *Data;
- } Patterns[PATTERNS] =
- {
- {0, &PatternData[0]},
- {3, &PatternData[1]},
- {2, &PatternData[9]},
- {2, &PatternData[13]},
- {2, &PatternData[17]},
- {3, &PatternData[21]}
- };
-
- #define MESSAGELINES 8
-
- char *Message[] =
- {
- "KeyBang 1.0",
- "by Mike Stark",
- "March 30, 1992",
- "",
- "--> Alt-Alt-F5 exits <--",
- "",
- "This program is shareware.",
- "Please read KeyBang.doc."
- };
-
- char *ScreenTitle = "KeyBang";
- struct IntuitionBase *IntuitionBase = NULL;
- struct GfxBase *GfxBase = NULL;
- struct Screen *BabyScreen = NULL;
- struct Window *BabyWindow = NULL, *IntroWindow = NULL;
- struct Remember *MemList = NULL;
- BYTE *BabyTmpRaster = NULL;
- APTR OldWindow;
- struct IOAudio *AudioMsg = NULL;
- struct MsgPort *IOReplyPort = NULL;
- struct MsgPort *KeyPort = NULL;
- struct IOStdReq *InputRequest = NULL;
- struct Interrupt HandlerInfo;
- struct SoundInfo **Sound;
- int Depth = 4;
- int Sounds = 0;
- int HandlerData[2];
- int LeftSoundPlaying = FALSE, RightSoundPlaying = FALSE;
- int WinX = 640, WinY = 200, XDPM, YDPM;
- int Unit[2];
- BOOL Audio = FALSE, OneShape = FALSE;
-
- main(argc, argv)
- int argc;
- char **argv;
-
- {
- struct MyInputEvent *Message;
- struct IntuiMessage *IMessage;
- struct IOAudio *SoundMsg;
- int Type, XSize, YSize, X, Y, Signal, Sample, SampleUnit;
- BOOL Done, DoAction, Mouse;
- int Count = 0, Seed, Pattern, Colors;
-
- GetOptions(argc, argv);
-
- Initialize();
-
- Colors = 1 << Depth;
-
- Signal = 1 << KeyPort->mp_SigBit;
- Signal |= 1 << IOReplyPort->mp_SigBit;
- Signal |= 1 << BabyWindow->UserPort->mp_SigBit;
-
- Done = FALSE;
- while (!Done)
- {
- DoAction = FALSE;
- Wait(Signal);
- if (Audio)
- while (SoundMsg = (struct IOAudio *)GetMsg(IOReplyPort))
- {
- SampleUnit = (int)SoundMsg->ioa_Request.io_Unit;
- if (SampleUnit & 9)
- RightSoundPlaying = FALSE;
- if (SampleUnit & 6)
- LeftSoundPlaying = FALSE;
- FreeMem(SoundMsg, sizeof(struct IOAudio));
- }
- while (Message = (struct MyInputEvent *)GetMsg(KeyPort))
- {
- if (Message->IE.ie_Class == IECLASS_RAWKEY)
- {
- if (!((Message->IE.ie_Code & IECODE_UP_PREFIX) ||
- (Message->IE.ie_Qualifier & IEQUALIFIER_REPEAT)))
- {
- DoAction = TRUE;
- Mouse = FALSE;
- }
- if (Message->IE.ie_Code == 0x45)
- {
- Erase(BabyWindow->RPort);
- }
- if ((Message->IE.ie_Code == 0x54) &&
- ((Message->IE.ie_Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))
- == (IEQUALIFIER_LALT | IEQUALIFIER_RALT)))
- {
- DoAction = FALSE;
- Done = TRUE;
- }
- }
- FreeMem(Message, sizeof(struct MyInputEvent));
- }
- while (IMessage = (struct IntuiMessage *)GetMsg(BabyWindow->UserPort))
- {
- if (!(IMessage->Code & IECODE_UP_PREFIX))
- {
- Mouse = TRUE;
- X = IMessage->MouseX; Y = IMessage->MouseY;
- YSize = Random(0) / 505 + 10;
- XSize = 2 * YSize * XDPM / YDPM;
- if (X < XSize) X = XSize; if (Y < YSize) Y = YSize;
- if (X > WinX - XSize) X = WinX - XSize;
- if (Y > WinY - YSize) Y = WinY - YSize;
- DoAction = TRUE;
- }
- ReplyMsg(IMessage);
- }
- if (DoAction)
- {
- if (IntroWindow)
- {
- CloseWindow(IntroWindow);
- IntroWindow= NULL;
- (void)Random(Seed);
- SetDrMd(BabyWindow->RPort, JAM2);
- }
- if (OneShape) Erase(BabyWindow->RPort);
- Sample = Random(0) * Sounds / 32768;
- if (Audio) MakeSound(Sample);
- if (!Mouse)
- {
- YSize = Random(0) / 505 + 10;
- XSize = 2 * YSize * XDPM / YDPM;
- Y = Random(0) * (WinY - 2 * YSize) / 32768 + YSize;
- X = Random(0) * (WinX - 2 * XSize) / 32768 + XSize;
- }
- Pattern = Random(0) * PATTERNS / 32768;
- SetAfPt(BabyWindow->RPort, Patterns[Pattern].Data, Patterns[Pattern].Power);
- SetOPen(BabyWindow->RPort, Random(0) * (Colors - 1) / 32768 + 1);
- SetAPen(BabyWindow->RPort, Random(0) * (Colors - 1) / 32768 + 1);
- SetBPen(BabyWindow->RPort, Random(0) * (Colors - 1) / 32768 + 1);
- Type = Random(0) * 5 / 32768;
- switch (Type)
- {
- case 0:
- Circle(BabyWindow->RPort, YSize, X, Y);
- break;
- default:
- Polygon(BabyWindow->RPort, Type + 2, YSize, X, Y);
- break;
- }
- }
- }
- CleanUp(FALSE);
- }
-
- Erase(RPort)
- struct RastPort *RPort;
-
- /********************\
- * Erase *
- * ----- *
- * Clear the KeyBang window. I know that there are more efficient ways of
- * doing this but this isn't too bad and that's how I coded it.
- \********************/
-
- {
- Move(RPort, 0, 0);
- SetDrMd(RPort, JAM1);
- SetAfPt(RPort, Patterns[0].Data, Patterns[0].Power);
- SetOPen(RPort, 0);
- SetAPen(RPort, 0);
- ClearScreen(RPort);
- SetDrMd(RPort, JAM2);
- }
-
- Polygon(RPort, Vertices, Size, X, Y)
- struct RastPort *RPort;
- int Size, X, Y;
-
- /********************\
- * Polygon *
- * ------- *
- * Draw a polygon with "Vertices" vertices and "Size" pixels high centered
- * at "X", "Y". Polygons are corrected for the aspect ratio of the screen. The
- * AreaInfo and TmpRas structures of the window into which the polygon is to
- * be drawn must be properly initialized. See Initialize.
- \********************/
-
- {
- int Phase, XPos, YPos, i;
-
- Phase = Random(0) * SINETABENTRIES / 32768;
- XPos = Size * SineTab[Phase] / 128;
- YPos = Size * SineTab[(Phase + SINETABENTRIES / 4) % SINETABENTRIES] / 128;
- AreaMove(RPort, X + 2 * XPos * XDPM / YDPM, Y + YPos);
- for (i = 1; i < Vertices; i++)
- {
- XPos = Size * SineTab[(i * SINETABENTRIES / Vertices + Phase)
- % SINETABENTRIES] / 128;
- YPos = Size * SineTab[(i * SINETABENTRIES / Vertices + Phase +
- SINETABENTRIES / 4) % SINETABENTRIES] / 128;
- AreaDraw(RPort, X + 2 * XDPM * XPos / YDPM, Y + YPos);
- }
- AreaEnd(RPort);
- }
-
- int Circle(RPort, Size, X, Y)
- struct RastPort *RPort;
- int Size, X, Y;
-
- /********************\
- * Circle *
- * ------ *
- * Draw a circle "Size" pixels high centered at "X", "Y". Circles are
- * corrected for the aspect ratio of the screen. The AreaInfo and TmpRas
- * structures of the window into which the circle is to be drawn must be
- * properly initialized. See Initialize.
- \********************/
-
- {
- AreaEllipse(RPort, X, Y, 2 * Size * XDPM / YDPM, Size);
- AreaEnd(RPort);
- }
-
-
- Initialize()
-
- /********************\
- * Initialize *
- * ---------- *
- * Allocates all of the resources that are used by the program. If some
- * of the resources are not available, this routine does not return.
- \********************/
-
- {
- struct NewWindow NewWindow;
- struct NewScreen NewScreen;
- SHORT *VectorTable;
- static UBYTE AudioChannels[] = {3, 5, 10, 12};
- extern struct Library *SysBase;
- int i, Width, Length;
- struct Process *ThisProcess;
-
- /* Open libraries */
-
- IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 29);
- if (IntuitionBase == NULL)
- CleanUp(FALSE);
- GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 29);
- if (GfxBase == NULL)
- CleanUp(FALSE);
-
- /* Get display size and aspect ratio from GfxBase */
-
- XDPM = GfxBase->NormalDPMX;
- YDPM = GfxBase->NormalDPMY;
- WinX = GfxBase->NormalDisplayColumns;
- WinY = GfxBase->NormalDisplayRows;
-
- /* Open the screen */
-
- NewScreen.LeftEdge = 0;
- NewScreen.TopEdge = 0;
- NewScreen.Width = WinX;
- NewScreen.Height = WinY;
- NewScreen.Depth = Depth;
- NewScreen.DetailPen = 1;
- NewScreen.BlockPen = 1;
- NewScreen.ViewModes = HIRES;
- NewScreen.Type = CUSTOMSCREEN;
- NewScreen.Font = NULL;
- NewScreen.DefaultTitle = (UBYTE *)ScreenTitle;
- NewScreen.Gadgets = NULL;
- NewScreen.CustomBitMap = NULL;
- if ((BabyScreen = (struct Screen *)OpenScreen(&NewScreen)) == NULL)
- CleanUp(FALSE);
-
- /* Open the window */
-
- NewWindow.LeftEdge = 0;
- NewWindow.TopEdge = 0;
- NewWindow.Width = WinX;
- NewWindow.Height = WinY;
- NewWindow.DetailPen = 1;
- NewWindow.BlockPen = 1;
- NewWindow.IDCMPFlags = MOUSEBUTTONS;
- NewWindow.Flags = SIMPLE_REFRESH | BORDERLESS | ACTIVATE | BACKDROP | RMBTRAP;
- NewWindow.FirstGadget = NULL;
- NewWindow.CheckMark = NULL;
- NewWindow.Title = NULL;
- NewWindow.Screen = BabyScreen;
- NewWindow.BitMap = NULL;
- NewWindow.MinWidth = WinX;
- NewWindow.MinHeight = WinY;
- NewWindow.MaxWidth = WinX;
- NewWindow.MaxHeight = WinY;
- NewWindow.Type = CUSTOMSCREEN;
- LoadRGB4(&BabyScreen->ViewPort, &ColorTable[0], 1 << Depth);
- if ((BabyWindow = (struct Window *)OpenWindow(&NewWindow)) == NULL)
- CleanUp(FALSE);
-
- /* Make system requexters come up on this screen */
-
- ThisProcess = (struct Process *)FindTask(0);
- OldWindow = ThisProcess->pr_WindowPtr;
- ThisProcess->pr_WindowPtr = (APTR)BabyWindow;
-
- /* Hide the screen title bar */
-
- ShowTitle(BabyScreen, FALSE);
-
- /* Open the message window */
-
- Width = 0;
- for (i = 0; i < MESSAGELINES; i++)
- {
- Length = TextLength(BabyWindow->RPort, Message[i], strlen(Message[i]));
- if (Length + 16 > Width) Width = Length + 16;
- }
- NewWindow.LeftEdge = WinX / 2 - Width / 2;
- NewWindow.TopEdge = 30;
- NewWindow.Width = Width;
- NewWindow.Height = 100;
- NewWindow.IDCMPFlags = NULL;
- NewWindow.Flags = SIMPLE_REFRESH;
- NewWindow.Title = (UBYTE *)ScreenTitle;
- NewWindow.MinWidth = Width;
- NewWindow.MinHeight = 100;
- NewWindow.MaxWidth = Width;
- NewWindow.MaxHeight = 100;
- if (IntroWindow = (struct Window *)OpenWindow(&NewWindow))
- {
- SetAPen(IntroWindow->RPort, 1);
- for (i = 0; i < MESSAGELINES; i++)
- {
- Length = TextLength(IntroWindow->RPort, Message[i], strlen(Message[i]));
- Move(IntroWindow->RPort, Width / 2 - Length / 2, 20 + 10 * i);
- Text(IntroWindow->RPort, Message[i], strlen(Message[i]));
- }
- }
- /* Open the AreaInfo and TmpRas structures used by the drawing routines */
-
- BabyWindow->RPort->TmpRas =
- (struct TmpRas *)AllocRemember(&MemList, sizeof(struct TmpRas), NULL);
- if (!BabyWindow->RPort->TmpRas)
- CleanUp(FALSE);
- if (!(BabyTmpRaster = AllocRaster(WinX, WinY)))
- CleanUp(FALSE);
- InitTmpRas(BabyWindow->RPort->TmpRas, BabyTmpRaster, RASSIZE(WinX, WinY));
- BabyWindow->RPort->AreaInfo =
- (struct AreaInfo *)AllocRemember(&MemList, sizeof(struct AreaInfo), NULL);
- if (!BabyWindow->RPort->AreaInfo)
- CleanUp(FALSE);
- if ((VectorTable = (SHORT *)AllocRemember(&MemList, VECTORS * 5, NULL))== NULL)
- CleanUp(FALSE);
- InitArea(BabyWindow->RPort->AreaInfo, VectorTable, VECTORS);
-
- /* Make the IO reply port for audio and input IO */
-
- if ((IOReplyPort = CreatePort("KeyBangIO", 0)) == NULL)
- CleanUp(FALSE);
-
- /* Make the port to receive messages from the input handler */
-
- if ((KeyPort = CreatePort("KeyBangKeys", 0)) == NULL)
- CleanUp(FALSE);
-
- /* Open the audio device */
-
- LoadSounds();
-
- if (Sounds)
- {
- AudioMsg = (struct IOAudio *)AllocRemember(&MemList, sizeof(struct IOAudio),
- MEMF_PUBLIC | MEMF_CLEAR);
- if (AudioMsg == NULL)
- CleanUp(FALSE);
- AudioMsg->ioa_Request.io_Message.mn_ReplyPort = IOReplyPort;
- AudioMsg->ioa_Request.io_Command = ADCMD_ALLOCATE;
- AudioMsg->ioa_Request.io_Flags = ADIOF_NOWAIT;
- AudioMsg->ioa_Data = AudioChannels;
- AudioMsg->ioa_Length = sizeof(AudioChannels);
- if (OpenDevice(AUDIONAME, 0 , AudioMsg, 0) == 0)
- {
- Audio = TRUE;
- Unit[0] = (int)AudioMsg->ioa_Request.io_Unit & 9;
- Unit[1] = (int)AudioMsg->ioa_Request.io_Unit & 6;
- }
- }
-
- /* Open the input device and install the input handler */
-
- if (!(InputRequest = CreateStdIO(IOReplyPort)))
- CleanUp(FALSE);
- if (OpenDevice("input.device", 0, InputRequest, 0))
- CleanUp(FALSE);
- HandlerData[0] = (int)KeyPort;
- HandlerData[1] = (int)SysBase;
- HandlerInfo.is_Data = (APTR)&HandlerData[0];
- HandlerInfo.is_Code = BabyInputHandler;
- HandlerInfo.is_Node.ln_Name = ScreenTitle;
- HandlerInfo.is_Node.ln_Pri = 75;
- InputRequest->io_Command = IND_ADDHANDLER;
- InputRequest->io_Data = (APTR)&HandlerInfo;
- DoIO(InputRequest);
- }
-
- LoadSounds()
-
- /********************\
- * LoadSounds *
- * ---------- *
- * Look into the sound directory and examine all the files. Those which
- * contain IFF 8SVX samples are loaded into an array so that they can be
- * played by MakeSound.
- \********************/
-
- {
- int SoundLength;
- struct FileLock *SoundLock;
- struct FileInfoBlock *FileInfoBlock;
- struct FileHandle *File;
- UBYTE *Buffer;
- char FileName[128];
- struct IFFHeader Header;
- struct SampleInfo SampleInfo;
-
- Sound = (struct SoundInfo **)AllocRemember(&MemList, 100 * 4, NULL);
- SoundLock = Lock(SOUNDDIRNAME, ACCESS_READ);
- if (!SoundLock)
- return;
- FileInfoBlock = (struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock), NULL);
- Examine(SoundLock, FileInfoBlock);
- while (ExNext(SoundLock, FileInfoBlock))
- {
- strcpy(FileName, SOUNDDIRNAME);
- strcat(FileName, FileInfoBlock->fib_FileName);
- File = Open(FileName, MODE_OLDFILE);
- if (File)
- {
- Read(File, &Header, 8);
- if (Header.Name == FORM)
- {
- Read(File, &Header, 4);
- if (Header.Name == EIGHT_SVX)
- {
- while (Read(File, &Header, 8) > 0)
- {
- switch (Header.Name)
- {
- case VHDR:
- Read(File, &SampleInfo, Header.Length);
- break;
- case BODY:
- Buffer = (UBYTE *)AllocRemember(&MemList, Header.Length,
- MEMF_CHIP | MEMF_PUBLIC);
- if (!Buffer) return;
- Read(File, Buffer, Header.Length);
- SoundLength = Header.Length;
- break;
- default:
- Seek(File, Header.Length, OFFSET_CURRENT);
- break;
- }
- }
- Sound[Sounds] =(struct SoundInfo *)AllocRemember(&MemList,
- sizeof(struct SoundInfo), NULL);
- if (!Sound[Sounds]) CleanUp(FALSE);
- Sound[Sounds]->Buffer = Buffer;
- Sound[Sounds]->SamplePeriod = CLOCK / SampleInfo.SampleRate;
- Sound[Sounds]->Volume = SampleInfo.Volume / 1024;
- Sound[Sounds]->Length = SoundLength;
- Sounds++;
- }
- }
- }
- Close(File);
- }
- UnLock(SoundLock);
- FreeMem(FileInfoBlock, sizeof(struct FileInfoBlock));
- }
-
- MakeSound(Sample)
- int Sample;
-
- /********************\
- * MakeSound *
- * --------- *
- * Play the sound "Sample". "Sample" is an index into the array of
- * sound samples loaded by LoadSounds. If one of the two channels opened by
- * KeyBang are busy, the sound is played in the other. If both are busy,
- * no sound is played.
- \********************/
-
- {
- BYTE *SoundData;
- struct IOAudio *SoundMsg;
- int i;
- static int UnitNum;
-
- if (LeftSoundPlaying)
- {
- if (RightSoundPlaying)
- return;
- else
- UnitNum = 0;
- }
- else
- {
- if (RightSoundPlaying)
- UnitNum = 1;
- else
- UnitNum = UnitNum - 2 * UnitNum + 1;
- }
- if (SoundMsg = (struct IOAudio *)AllocMem(sizeof(struct IOAudio), MEMF_PUBLIC))
- {
- SoundMsg->ioa_Request.io_Message.mn_ReplyPort = IOReplyPort;
- SoundMsg->ioa_Request.io_Device = AudioMsg->ioa_Request.io_Device;
- SoundMsg->ioa_Request.io_Unit = (struct Unit *)Unit[UnitNum];
- SoundMsg->ioa_Request.io_Command = CMD_WRITE;
- SoundMsg->ioa_Request.io_Flags = ADIOF_PERVOL;
- SoundMsg->ioa_AllocKey = AudioMsg->ioa_AllocKey;
- SoundMsg->ioa_Length = Sound[Sample]->Length;
- SoundMsg->ioa_Period = Sound[Sample]->SamplePeriod;
- SoundMsg->ioa_Volume = 64;
- SoundMsg->ioa_Cycles = 1;
- SoundMsg->ioa_Data = Sound[Sample]->Buffer;
- BeginIO(SoundMsg);
- if (Unit[UnitNum] & 9)
- RightSoundPlaying = TRUE;
- if (Unit[UnitNum] & 6)
- LeftSoundPlaying = TRUE;
- }
- }
-
- CleanUp(Flag)
- BOOL Flag;
-
- /********************\
- * CleanUp *
- * ------- *
- * Deallocate all resources. I have tried to reply to all messages
- * which may be waiting on ports before deleting them.
- \********************/
- {
- struct Message *TempPointer;
- struct Process *ThisProcess;
-
- if (Flag)
- puts("Usage : KeyBang [-colors {2|4|8|16}] [-oneshape]");
- if (InputRequest)
- {
- InputRequest->io_Command = IND_REMHANDLER;
- InputRequest->io_Data = (APTR)&HandlerInfo;
- DoIO(InputRequest);
- CloseDevice(InputRequest);
- DeleteStdIO(InputRequest);
- }
- if (Audio) CloseDevice(AudioMsg);
- if (IOReplyPort)
- DeletePort(IOReplyPort);
- if (KeyPort)
- {
- while (TempPointer = GetMsg(KeyPort))
- FreeMem(TempPointer, sizeof(struct MyInputEvent));
- DeletePort(KeyPort);
- }
- if (BabyTmpRaster) FreeRaster(BabyTmpRaster, WinX, WinY);
- if (IntroWindow) CloseWindow(IntroWindow);
- if (BabyWindow)
- {
- ThisProcess = (struct Process *)FindTask(0);
- ThisProcess->pr_WindowPtr = OldWindow;
- CloseWindow(BabyWindow);
- }
- if (BabyScreen) CloseScreen(BabyScreen);
- if (MemList) FreeRemember(&MemList, TRUE);
- if (GfxBase) CloseLibrary(GfxBase);
- if (IntuitionBase) CloseLibrary(IntuitionBase);
- exit(0);
- }
-
- int Random(UserSeed)
- unsigned long int UserSeed;
-
- {
- static unsigned long int Seed;
-
- if (UserSeed) Seed = UserSeed;
- Seed = Seed * 1103515245 + 12345;
- return (unsigned int)(Seed/65536) % 32768;
- }
-