void PadPict(char poff) { SimpleHdr table; FILE *in; display::AutoPal p(display::graphics.legacyScreen()); in = sOpen("LFACIL.BUT", "rb", 0); fread_SimpleHdr(&table, 1, in); fseek(in, 6 * sizeof_SimpleHdr, SEEK_SET); fread(p.pal, 768, 1, in); fseek(in, table.offset, SEEK_SET); fread(buffer, table.size, 1, in); display::LegacySurface local(148, 148); display::LegacySurface local2(148, 148); RLED_img(buffer, local.pixels(), table.size, local.width(), local.height()); fseek(in, (poff)*sizeof_SimpleHdr, SEEK_SET); fread_SimpleHdr(&table, 1, in); fseek(in, table.offset, SEEK_SET); fread(buffer, table.size, 1, in); RLED_img(buffer, local2.pixels(), table.size, local2.width(), local2.height()); local2.copyTo(display::graphics.legacyScreen(), 168, 28); fclose(in); }
void Display_ARROW(char num, int x, int y) { /* Look for explanations in place.c:PatchMe() */ PatchHdrSmall P; FILE *in; in = sOpen("ARROWS.BUT", "rb", 0); fseek(in, (num) * (sizeof P), SEEK_CUR); fread(&P, sizeof P, 1, in); SwapPatchHdrSmall(&P); fseek(in, P.offset, SEEK_SET); if (P.w * P.h != P.size) { /* fprintf(stderr, "Display_ARROW(): w*h != size (%hhd*%hhd == %d != %hd)\n", P.w, P.h, P.w*P.h, P.size); */ if ((P.w + 1) * P.h == P.size) { /* fprintf(stderr, "Display_ARROW(): P.w++ saves the day!\n"); */ P.w++; } P.size = P.w * P.h; } display::Surface local(P.w, P.h); display::Surface local2(P.w, P.h); local2.copyFrom(display::graphics.screen(), x, y, x + P.w - 1, y + P.h - 1); fread(local.pixels(), P.size, 1, in); fclose(in); // for (j=0;j<P.size;j++) // if(local.vptr[j]!=0) local2.vptr[j]=local.vptr[j]; local.copyTo(display::graphics.screen(), x, y); }
clsparseStatus reduce_by_key( int keys_first, int keys_last, int values_first, cl_mem keys_input, cl_mem values_input, cl_mem keys_output, cl_mem values_output, int *count, clsparseControl control ) { cl_int l_Error; /********************************************************************************** * Compile Options *********************************************************************************/ const int kernel0_WgSize = WAVESIZE*KERNEL02WAVES; const int kernel1_WgSize = WAVESIZE*KERNEL1WAVES; const int kernel2_WgSize = WAVESIZE*KERNEL02WAVES; //const std::string params = std::string() + // " -DKERNEL0WORKGROUPSIZE=" + std::to_string(kernel0_WgSize) // + " -DKERNEL1WORKGROUPSIZE=" + std::to_string(kernel1_WgSize) // + " -DKERNEL2WORKGROUPSIZE=" + std::to_string(kernel2_WgSize); const std::string params; cl::Context context = control->getContext(); std::vector<cl::Device> dev = context.getInfo<CL_CONTEXT_DEVICES>(); int computeUnits = dev[0].getInfo< CL_DEVICE_MAX_COMPUTE_UNITS >( ); int wgPerComputeUnit = dev[0].getInfo< CL_DEVICE_MAX_WORK_GROUP_SIZE >( ); int resultCnt = computeUnits * wgPerComputeUnit; cl_uint numElements = keys_last - keys_first + 1; size_t sizeInputBuff = numElements; int modWgSize = (sizeInputBuff & (kernel0_WgSize-1)); if( modWgSize ) { sizeInputBuff &= ~modWgSize; sizeInputBuff += kernel0_WgSize; } cl_uint numWorkGroupsK0 = static_cast< cl_uint >( sizeInputBuff / kernel0_WgSize ); size_t sizeScanBuff = numWorkGroupsK0; modWgSize = (sizeScanBuff & (kernel0_WgSize-1)); if( modWgSize ) { sizeScanBuff &= ~modWgSize; sizeScanBuff += kernel0_WgSize; } cl_mem tempArrayVec = clCreateBuffer(context(),CL_MEM_READ_WRITE, (numElements)*sizeof(int), NULL, NULL ); /********************************************************************************** * Kernel 0 *********************************************************************************/ cl::Kernel kernel0 = KernelCache::get(control->queue,"reduce_by_key", "OffsetCalculation", params); KernelWrap kWrapper0(kernel0); kWrapper0 << keys_input << tempArrayVec << numElements; cl::NDRange local0(kernel0_WgSize); cl::NDRange global0(sizeInputBuff); cl_int status = kWrapper0.run(control, global0, local0); if (status != CL_SUCCESS) { return clsparseInvalidKernelExecution; } int init = 0; scan(0, numElements - 1, tempArrayVec, tempArrayVec, 0, 0, control ); int pattern = 0; cl_mem keySumArray = clCreateBuffer(context(),CL_MEM_READ_WRITE, (sizeScanBuff)*sizeof(int), NULL, NULL ); cl_mem preSumArray = clCreateBuffer(context(),CL_MEM_READ_WRITE, (sizeScanBuff)*sizeof(int), NULL, NULL ); cl_mem postSumArray = clCreateBuffer(context(),CL_MEM_READ_WRITE,(sizeScanBuff)*sizeof(int), NULL, NULL ); clEnqueueFillBuffer(control->queue(), keySumArray, &pattern, sizeof(int), 0, (sizeScanBuff)*sizeof(int), 0, NULL, NULL); clEnqueueFillBuffer(control->queue(), preSumArray, &pattern, sizeof(int), 0, (sizeScanBuff)*sizeof(int), 0, NULL, NULL); clEnqueueFillBuffer(control->queue(), postSumArray, &pattern, sizeof(int), 0, (sizeScanBuff)*sizeof(int), 0, NULL, NULL); /********************************************************************************** * Kernel 1 *********************************************************************************/ cl::Kernel kernel1 = KernelCache::get(control->queue,"reduce_by_key", "perBlockScanByKey", params); KernelWrap kWrapper1(kernel1); kWrapper1 << tempArrayVec << values_input << numElements << keySumArray << preSumArray; cl::NDRange local1(kernel0_WgSize); cl::NDRange global1(sizeInputBuff); status = kWrapper1.run(control, global1, local1); if (status != CL_SUCCESS) { return clsparseInvalidKernelExecution; } /********************************************************************************** * Kernel 2 *********************************************************************************/ cl_uint workPerThread = static_cast< cl_uint >( sizeScanBuff / kernel1_WgSize ); cl::Kernel kernel2 = KernelCache::get(control->queue,"reduce_by_key", "intraBlockInclusiveScanByKey", params); KernelWrap kWrapper2(kernel2); kWrapper2 << keySumArray << preSumArray << postSumArray << numWorkGroupsK0 << workPerThread; cl::NDRange local2(kernel1_WgSize); cl::NDRange global2(kernel1_WgSize); status = kWrapper2.run(control, global2, local2); if (status != CL_SUCCESS) { return clsparseInvalidKernelExecution; } /********************************************************************************** * Kernel 3 *********************************************************************************/ cl::Kernel kernel3 = KernelCache::get(control->queue,"reduce_by_key", "keyValueMapping", params); KernelWrap kWrapper3(kernel3); kWrapper3 << keys_input << keys_output << values_input << values_output << tempArrayVec << keySumArray << postSumArray << numElements; cl::NDRange local3(kernel0_WgSize); cl::NDRange global3(sizeInputBuff); status = kWrapper3.run(control, global3, local3); if (status != CL_SUCCESS) { return clsparseInvalidKernelExecution; } int *h_result = (int *) malloc (sizeof(int)); clEnqueueReadBuffer(control->queue(), tempArrayVec, 1, (numElements-1)*sizeof(int), sizeof(int), h_result, 0, 0, 0); *count = *(h_result); //printf("h_result = %d\n", *count ); //release buffers clReleaseMemObject(tempArrayVec); clReleaseMemObject(preSumArray); clReleaseMemObject(postSumArray); clReleaseMemObject(keySumArray); return clsparseSuccess; } //end of reduce_by_key
int main(int argc, char *argv[]) { Pooma::initialize(argc, argv); Pooma::Tester tester(argc, argv); // To declare a field, you first need to set up a layout. This requires // knowing the physical vertex-domain and the number of external guard // cell layers. Vertex domains contain enough points to hold all of the // rectilinear centerings that POOMA is likely to support for quite // awhile. Also, it means that the same layout can be used for all // fields, regardless of centering. Interval<2> physicalVertexDomain(14, 14); Loc<2> blocks(3, 3); GridLayout<2> layout1(physicalVertexDomain, blocks, GuardLayers<2>(1), LayoutTag_t()); GridLayout<2> layout0(physicalVertexDomain, blocks, GuardLayers<2>(0), LayoutTag_t()); Centering<2> cell = canonicalCentering<2>(CellType, Continuous, AllDim); Centering<2> vert = canonicalCentering<2>(VertexType, Continuous, AllDim); Centering<2> yedge = canonicalCentering<2>(EdgeType, Continuous, YDim); Vector<2> origin(0.0); Vector<2> spacings(1.0, 2.0); // First basic test verifies that we're assigning to the correct areas // on a brick. typedef Field<UniformRectilinearMesh<2>, double, MultiPatch<GridTag, BrickTag_t> > Field_t; Field_t b0(cell, layout1, origin, spacings); Field_t b1(vert, layout1, origin, spacings); Field_t b2(yedge, layout1, origin, spacings); Field_t b3(yedge, layout1, origin, spacings); Field_t bb0(cell, layout0, origin, spacings); Field_t bb1(vert, layout0, origin, spacings); Field_t bb2(yedge, layout0, origin, spacings); b0.all() = 0.0; b1.all() = 0.0; b2.all() = 0.0; b0 = 1.0; b1 = 1.0; b2 = 1.0; bb0.all() = 0.0; bb1.all() = 0.0; bb2.all() = 0.0; bb0 = 1.0; bb1 = 1.0; bb2 = 1.0; // SPMD code follows. // Note, SPMD code will work with the evaluator if you are careful // to perform assignment on all the relevant contexts. The patchLocal // function creates a brick on the local context, so you can just perform // the assignment on that context. int i; for (i = 0; i < b0.numPatchesLocal(); ++i) { Patch<Field_t>::Type_t patch = b0.patchLocal(i); // tester.out() << "context " << Pooma::context() << ": assigning to patch " << i // << " with domain " << patch.domain() << std::endl; patch += 1.5; } // This is safe to do since b1 and b2 are built with the same layout. for (i = 0; i < b1.numPatchesLocal(); ++i) { b1.patchLocal(i) += 1.5; b2.patchLocal(i) += 1.5; } for (i = 0; i < bb0.numPatchesLocal(); ++i) { Patch<Field_t>::Type_t patch = bb0.patchLocal(i); // tester.out() << "context " << Pooma::context() << ": assigning to patch on bb0 " << i // << " with domain " << patch.domain() << std::endl; patch += 1.5; } // This is safe to do since bb1 and bb2 are built with the same layout. for (i = 0; i < bb1.numPatchesLocal(); ++i) { bb1.patchLocal(i) += 1.5; bb2.patchLocal(i) += 1.5; } tester.check("cell centered field is 2.5", all(b0 == 2.5)); tester.check("vert centered field is 2.5", all(b1 == 2.5)); tester.check("edge centered field is 2.5", all(b2 == 2.5)); tester.out() << "b0.all():" << std::endl << b0.all() << std::endl; tester.out() << "b1.all():" << std::endl << b1.all() << std::endl; tester.out() << "b2.all():" << std::endl << b2.all() << std::endl; tester.check("didn't write into b0 boundary", sum(b0.all()) == 2.5 * b0.physicalDomain().size()); tester.check("didn't write into b1 boundary", sum(b1.all()) == 2.5 * b1.physicalDomain().size()); tester.check("didn't write into b2 boundary", sum(b2.all()) == 2.5 * b2.physicalDomain().size()); tester.check("cell centered field is 2.5", all(bb0 == 2.5)); tester.check("vert centered field is 2.5", all(bb1 == 2.5)); tester.check("edge centered field is 2.5", all(bb2 == 2.5)); tester.out() << "bb0:" << std::endl << bb0 << std::endl; tester.out() << "bb1:" << std::endl << bb1 << std::endl; tester.out() << "bb2:" << std::endl << bb2 << std::endl; typedef Field<UniformRectilinearMesh<2>, double, MultiPatch<GridTag, CompressibleBrickTag_t> > CField_t; CField_t c0(cell, layout1, origin, spacings); CField_t c1(vert, layout1, origin, spacings); CField_t c2(yedge, layout1, origin, spacings); CField_t cb0(cell, layout0, origin, spacings); CField_t cb1(vert, layout0, origin, spacings); CField_t cb2(yedge, layout0, origin, spacings); c0.all() = 0.0; c1.all() = 0.0; c2.all() = 0.0; c0 = 1.0; c1 = 1.0; c2 = 1.0; cb0.all() = 0.0; cb1.all() = 0.0; cb2.all() = 0.0; cb0 = 1.0; cb1 = 1.0; cb2 = 1.0; // SPMD code follows. // Note, SPMD code will work with the evaluator if you are careful // to perform assignment on all the relevant contexts. The patchLocal // function creates a brick on the local context, so you can just perform // the assignment on that context. for (i = 0; i < c0.numPatchesLocal(); ++i) { Patch<CField_t>::Type_t patch = c0.patchLocal(i); tester.out() << "context " << Pooma::context() << ": assigning to patch " << i << " with domain " << patch.domain() << std::endl; patch += 1.5; } // This is safe to do since c1 and c2 are built with the same layout. for (i = 0; i < c1.numPatchesLocal(); ++i) { c1.patchLocal(i) += 1.5; c2.patchLocal(i) += 1.5; } for (i = 0; i < cb0.numPatchesLocal(); ++i) { Patch<CField_t>::Type_t patch = cb0.patchLocal(i); tester.out() << "context " << Pooma::context() << ": assigning to patch on cb0 " << i << " with domain " << patch.domain() << std::endl; patch += 1.5; } // This is safe to do since cb1 and cb2 are cuilt with the same layout. for (i = 0; i < cb1.numPatchesLocal(); ++i) { cb1.patchLocal(i) += 1.5; cb2.patchLocal(i) += 1.5; } tester.check("cell centered field is 2.5", all(c0 == 2.5)); tester.check("vert centered field is 2.5", all(c1 == 2.5)); tester.check("edge centered field is 2.5", all(c2 == 2.5)); tester.out() << "c0.all():" << std::endl << c0.all() << std::endl; tester.out() << "c1.all():" << std::endl << c1.all() << std::endl; tester.out() << "c2.all():" << std::endl << c2.all() << std::endl; tester.check("didn't write into c0 boundary", sum(c0.all()) == 2.5 * c0.physicalDomain().size()); tester.check("didn't write into c1 boundary", sum(c1.all()) == 2.5 * c1.physicalDomain().size()); tester.check("didn't write into c2 boundary", sum(c2.all()) == 2.5 * c2.physicalDomain().size()); tester.check("cell centered field is 2.5", all(cb0 == 2.5)); tester.check("vert centered field is 2.5", all(cb1 == 2.5)); tester.check("edge centered field is 2.5", all(cb2 == 2.5)); tester.out() << "cb0:" << std::endl << cb0 << std::endl; tester.out() << "cb1:" << std::endl << cb1 << std::endl; tester.out() << "cb2:" << std::endl << cb2 << std::endl; //------------------------------------------------------------------ // Scalar code example: // c0 = iota(c0.domain()).comp(0); c1 = iota(c1.domain()).comp(1); // Make sure all the data-parallel are done: Pooma::blockAndEvaluate(); for (i = 0; i < c0.numPatchesLocal(); ++i) { Patch<CField_t>::Type_t local0 = c0.patchLocal(i); Patch<CField_t>::Type_t local1 = c1.patchLocal(i); Patch<CField_t>::Type_t local2 = c2.patchLocal(i); Interval<2> domain = local2.domain(); // physical domain of local y-edges // -------------------------------------------------------------- // I believe the following is probably the most efficient approach // for sparse computations. For data-parallel computations, the // evaluator will uncompress the patches and take brick views, which // provide the most efficient access. If you are only performing // the computation on a small portion of cells, then the gains would // be outweighed by the act of copying the compressed value to all the // cells. // // The read function is used on the right hand side, because // operator() is forced to uncompress the patch just in case you want // to write to it. for(Interval<2>::iterator pos = domain.begin(); pos != domain.end(); ++pos) { Loc<2> edge = *pos; Loc<2> rightCell = edge; // cell to right is same cell Loc<2> leftCell = edge - Loc<2>(1,0); Loc<2> topVert = edge + Loc<2>(0, 1); Loc<2> bottomVert = edge; local2(edge) = local0.read(rightCell) + local0.read(leftCell) + local1.read(topVert) + local1.read(bottomVert); } // This statement is optional, it tries to compress the patch after // we're done computing on it. Since I used .read() for the local0 and 1 // they remained in their original state. compress() can be expensive, so // it may not be worth trying unless space is really important. compress(local2); } tester.out() << "c0" << std::endl << c0 << std::endl; tester.out() << "c1" << std::endl << c1 << std::endl; tester.out() << "c2" << std::endl << c2 << std::endl; //------------------------------------------------------------------ // Interfacing with a c-function: // // This example handles the corner cases, where the patches from a // cell centered field with no guard layers actually contain some // extra data. Pooma::blockAndEvaluate(); for (i = 0; i < cb0.numPatchesLocal(); ++i) { Patch<CField_t>::Type_t local0 = cb0.patchLocal(i); Interval<2> physicalDomain = local0.physicalDomain(); double *data; int size = physicalDomain.size(); if (physicalDomain == local0.totalDomain()) { uncompress(local0); data = &local0(physicalDomain.firsts()); nonsense(data, size); } else { // In this case, the engine has extra storage even though the // field has the right domain. We copy it to a brick engine, // call the function and copy it back. No uncompress is required, // since the assignment will copy the compressed value into the // brick. // arrayView is a work-around. Array = Field doesn't work at // the moment. Array<2, double, Brick> brick(physicalDomain); Array<2, double, CompressibleBrick> arrayView(local0.engine()); brick = arrayView(physicalDomain); Pooma::blockAndEvaluate(); data = &brick(Loc<2>(0)); nonsense(data, size); arrayView(physicalDomain) = brick; // Note that we don't need a blockAndEvaluate here, since an iterate has // been spawned to perform the copy. } // If you want to try compress(local0) here, you should do blockAndEvaluate // first in case the local0 = brick hasn't been executed yet. } tester.out() << "cb0.all()" << std::endl << cb0 << std::endl; b2 = positions(b2).comp(0); RefCountedBlockPtr<double> block = pack(b2); // The following functions give you access to the raw data from pack. // Note that the lifetime of the data is managed by the RefCountedBlockPtr, // so when "block" goes out of scope, the data goes away. (i.e. Don't write // a function where you return block.beginPointer().) double *start = block.beginPointer(); // start of the data double *end = block.endPointer(); // one past the end int size = block.size(); // size of the data tester.out() << Pooma::context() << ":" << block.size() << std::endl; unpack(b3, block); tester.out() << "b2" << std::endl << b2 << std::endl; tester.out() << "b3" << std::endl << b3 << std::endl; tester.check("pack, unpack", all(b2 == b3)); int ret = tester.results("LocalPatch"); Pooma::finalize(); return ret; }
/* The main control loop for the Future Missions feature. */ void Future(char plr) { /** \todo the whole Future()-function is 500 >lines and unreadable */ TRACE1("->Future(plr)"); int MisNum = 0, DuraType = 0, MaxDur = 6; int setting = -1, prev_setting = -1; display::LegacySurface local(166, 9); display::LegacySurface local2(177, 197); vh = new display::LegacySurface(240, 90); unsigned int year = Data->Year; unsigned int season = Data->Season; TRACE3("--- Setting year=Year (%d), season=Season (%d)", year, season); SetParameters(); MarsFlag = MarsInRange(year, season); JupiterFlag = JupiterInRange(year, season); SaturnFlag = SaturnInRange(year, season); while ((MisNum = FutureCheck(plr, 0)) != 5) { F1 = F2 = F3 = F4 = F5 = 0; for (int i = 0; i < 5; i++) { lock[i] = false; status[i] = 0; } keyHelpText = "k011"; helpText = "i011"; Pad = MisNum; DuraType = 0; MisType = 0; ClrFut(plr, MisNum); JointFlag = JointMissionOK(plr, MisNum); // initialize joint flag if (JointFlag == false) { F4 = 2; lock[4] = true; status[4] = 0; } DrawFuture(plr, MisType, MisNum); while (1) { key = 0; GetMouse(); prev_setting = setting; setting = -1; // SEG determines the number of control points used in creating // the B-splines for drawing the mission flight path. // The more control points, the smoother the path should // appear. if (key == '-' && SEG > 1) { SEG--; } else if (key == '+' && SEG < 500) { SEG++; } else if (key >= 65 && key < Bub_Count + 65) { setting = key - 65; } // If the mouse is over one of the Mission Step bubbles, // display the step information. for (int i = 0; i < Bub_Count; i++) { if (x >= StepBub[i].x_cor && x <= StepBub[i].x_cor + 7 && y >= StepBub[i].y_cor && y <= StepBub[i].y_cor + 7) { setting = i; break; } } if (setting >= 0) { if (prev_setting < 0) { local.copyFrom(display::graphics.legacyScreen(), 18, 186, 183, 194); } if (prev_setting != setting) { ShBox(18, 186, 183, 194); display::graphics.setForegroundColor(1); MisStep(21, 192, Mev[setting].loc); } } else if (setting < 0 && prev_setting >= 0) { local.copyTo(display::graphics.legacyScreen(), 18, 186); } if (Mis.Dur <= V[MisType].E && ((x >= 244 && y >= 5 && x <= 313 && y <= 17 && mousebuttons > 0) || key == K_ENTER)) { InBox(244, 5, 313, 17); WaitForMouseUp(); if (key > 0) { delay(300); } key = 0; OutBox(244, 5, 313, 17); // Copy the screen contents to a buffer. If the mission // requires a capsule to be assigned, a pop-up will be // created listing the options. Once the pop-up is // dismissed the screen may be redrawn from the buffer. local2.copyFrom(display::graphics.legacyScreen(), 74, 3, 250, 199); int NewType = V[MisType].X; Data->P[plr].Future[MisNum].Duration = DuraType; int Ok = HardCrewAssign(plr, MisNum, MisType, NewType); local2.copyTo(display::graphics.legacyScreen(), 74, 3); if (Ok == 1) { Data->P[plr].Future[MisNum].Duration = DuraType; break; // return to launchpad loop } else { ClrFut(plr, MisNum); continue; } } else if ((x >= 43 && y >= 74 && x <= 53 && y <= 82 && mousebuttons > 0) || key == '!') { // Duration restriction lock lock[0] = (! lock[0]); if (lock[0] == true) { InBox(43, 74, 53, 82); PlaceRX(1); F5 = (status[0] == 0) ? -1 : status[0]; } else { OutBox(43, 74, 53, 82); ClearRX(1); F5 = status[0] = 0; } WaitForMouseUp(); } else if (lock[0] != true && ((x >= 5 && y >= 49 && x <= 53 && y <= 72 && mousebuttons > 0) || key == '1')) { // Duration toggle InBox(5, 49, 53, 72); if (DuraType == MaxDur) { DuraType = 0; } else { DuraType++; } Data->P[plr].Future[MisNum].Duration = DuraType; if (DuraType == 0) { Toggle(5, 0); } else if (DuraType == 1) { Toggle(5, 1); } if (DuraType != 0) { draw_Pie(DuraType); } status[0] = DuraType; WaitForMouseUp(); display::graphics.setForegroundColor(34); OutBox(5, 49, 53, 72); } else if ((x >= 5 && y >= 74 && x <= 41 && y <= 82 && mousebuttons > 0) || (key == K_ESCAPE)) { // Reset mission selection InBox(5, 74, 41, 82); WaitForMouseUp(); MisType = 0; DuraType = F1 = F2 = F3 = F4 = F5 = 0; for (int i = 0; i < 5; i++) { lock[i] = false; status[i] = 0; } if (JointFlag == false) { F4 = 2; lock[4] = true; InBox(191, 74, 201, 82); TogBox(166, 49, 1); } else { OutBox(191, 74, 201, 82); } OutBox(5, 49, 53, 72); OutBox(43, 74, 53, 82); OutBox(80, 74, 90, 82); OutBox(117, 74, 127, 82); OutBox(154, 74, 164, 82); ClrFut(plr, MisNum); Missions(plr, 8, 37, MisType, 1); GetMinus(plr); OutBox(5, 74, 41, 82); } else if ((x >= 80 && y >= 74 && x <= 90 && y <= 82 && mousebuttons > 0) || key == '@') { // Docking restriction lock lock[1] = (! lock[1]); if (lock[1] == true) { InBox(80, 74, 90, 82); PlaceRX(2); } else { OutBox(80, 74, 90, 82); ClearRX(2); } if ((status[1] == 0) && (lock[1] == true)) { F1 = 2; } else if ((status[1] == 1) && (lock[1] == true)) { F1 = 1; } else { F1 = 0; } WaitForMouseUp(); } else if (lock[1] == false && (((x >= 55 && y >= 49 && x <= 90 && y <= 82) && mousebuttons > 0) || key == '2')) { // Docking toggle TogBox(55, 49, 1); if (status[1] == 0) { Toggle(1, 1); } else { Toggle(1, 0); } status[1] = abs(status[1] - 1); WaitForMouseUp(); TogBox(55, 49, 0); } else if ((x >= 117 && y >= 74 && x <= 127 && y <= 82 && mousebuttons > 0) || key == '#') { // EVA Restriction button lock[2] = (! lock[2]); if (lock[2] == true) { InBox(117, 74, 127, 82); PlaceRX(3); } else { OutBox(117, 74, 127, 82); ClearRX(3); } if ((status[2] == 0) && (lock[2] == true)) { F2 = 2; } else if ((status[2] == 1) && (lock[2] == true)) { F2 = 1; } else { F2 = 0; } WaitForMouseUp(); } else if (lock[2] == false && ((x >= 92 && y >= 49 && x <= 127 && y <= 82 && mousebuttons > 0) || key == '3')) { // EVA toggle TogBox(92, 49, 1); if (status[2] == 0) { Toggle(2, 1); } else { Toggle(2, 0); } status[2] = abs(status[2] - 1); WaitForMouseUp(); TogBox(92, 49, 0); } else if ((x >= 154 && y >= 74 && x <= 164 && y <= 82 && mousebuttons > 0) || key == '$') { // Lunar Module Restriction button lock[3] = (! lock[3]); if (lock[3] == true) { InBox(154, 74, 164, 82); PlaceRX(4); } else { OutBox(154, 74, 164, 82); ClearRX(4); } if ((status[3] == 0) && (lock[3] == true)) { F3 = 2; } else if ((status[3] == 1) && (lock[3] == true)) { F3 = 1; } else { F3 = 0; } WaitForMouseUp(); } else if (lock[3] == false && ((x >= 129 && y >= 49 && x <= 164 && y <= 82 && mousebuttons > 0) || key == '4')) { // LEM toggle TogBox(129, 49, 1); if (status[3] == 0) { Toggle(3, 1); } else { Toggle(3, 0); } status[3] = abs(status[3] - 1); WaitForMouseUp(); TogBox(129, 49, 0); } else if (JointFlag == true && ((x > 191 && y >= 74 && x <= 201 && y <= 82 && mousebuttons > 0) || key == '%')) { // Joint Mission Restriction button lock[4] = (! lock[4]); if (lock[4] == true) { InBox(191, 74, 201, 82); PlaceRX(5); } else { OutBox(191, 74, 201, 82); ClearRX(5); } if ((status[4] == 0) && (lock[4] == true)) { F4 = 2; } else if ((status[4] == 1) && (lock[4] == true)) { F4 = 1; } else { F4 = 0; } WaitForMouseUp(); } else if (lock[4] == false && JointFlag == true && ((x >= 166 && y >= 49 && x <= 201 && y <= 82 && mousebuttons > 0) || key == '5')) { // Joint Mission TogBox(166, 49, 1); status[4] = abs(status[4] - 1); if (status[4] == 0) { Toggle(4, 1); } else { Toggle(4, 0); } WaitForMouseUp(); TogBox(166, 49, 0); } else if ((x >= 5 && y >= 84 && x <= 16 && y <= 130 && mousebuttons > 0) || (key == UP_ARROW)) { // Scroll up among Mission Types InBox(5, 84, 16, 130); for (int i = 0; i < 50; i++) { key = 0; GetMouse(); delay(10); if (mousebuttons == 0) { MisType = UpSearchRout(MisType, plr); Data->P[plr].Future[MisNum].MissionCode = MisType; i = 51; } } // Keep scrolling while mouse/key is held down. while (mousebuttons == 1 || key == UP_ARROW) { MisType = UpSearchRout(MisType, plr); Data->P[plr].Future[MisNum].MissionCode = MisType; Missions(plr, 8, 37, MisType, 3); delay(100); key = 0; GetMouse(); } Missions(plr, 8, 37, MisType, 3); DuraType = status[0]; OutBox(5, 84, 16, 130); } else if ((x >= 5 && y >= 132 && x < 16 && y <= 146 && mousebuttons > 0) || (key == K_SPACE)) { // Turn on Mission Steps display InBox(5, 132, 16, 146); WaitForMouseUp(); delay(50); MisType = Data->P[plr].Future[MisNum].MissionCode; assert(0 <= MisType); if (MisType != 0) { Missions(plr, 8, 37, MisType, 1); } else { Missions(plr, 8, 37, MisType, 3); } OutBox(5, 132, 16, 146); } else if ((x >= 5 && y >= 148 && x <= 16 && y <= 194 && mousebuttons > 0) || (key == DN_ARROW)) { // Scroll down among Mission Types InBox(5, 148, 16, 194); for (int i = 0; i < 50; i++) { key = 0; GetMouse(); delay(10); if (mousebuttons == 0) { MisType = DownSearchRout(MisType, plr); Data->P[plr].Future[MisNum].MissionCode = MisType; i = 51; } } // Keep scrolling while mouse/key is held down. while (mousebuttons == 1 || key == DN_ARROW) { MisType = DownSearchRout(MisType, plr); Data->P[plr].Future[MisNum].MissionCode = MisType; Missions(plr, 8, 37, MisType, 3); delay(100); key = 0; GetMouse(); } Missions(plr, 8, 37, MisType, 3); DuraType = status[0]; OutBox(5, 148, 16, 194); } } // Input while loop } // Launch pad selection loop delete vh; vh = NULL; TRACE1("<-Future()"); }