#include #include #include #include #include #include #include #include #include #include #include int main(int argc, char** argv) { /* Init logging. We log both to Cafe's internal logger (shows up in Decaf, some crash logs) and over UDP to be received with udplogserver. */ WHBLogCafeInit(); /* WHBLogPrint and WHBLogPrintf add new line characters for you */ WHBLogPrint("Hello World! Logging initialised."); /* Init WHB's ProcUI wrapper. This will manage all the little Cafe OS bits and pieces for us - home menu overlay, power saving features, etc. */ WHBProcInit(); /* Init OSScreen. This is the really simple graphics API we'll be using to draw some text! */ OSScreenInit(); /* OSScreen needs buffers for each display - get the size of those now. "DRC" is Nintendo's acronym for the Gamepad. */ size_t tvBufferSize = OSScreenGetBufferSizeEx(SCREEN_TV); size_t drcBufferSize = OSScreenGetBufferSizeEx(SCREEN_DRC); WHBLogPrintf("Will allocate 0x%X bytes for the TV, " \ "and 0x%X bytes for the DRC.", tvBufferSize, drcBufferSize); /* Try to allocate an area for the buffers. According to OSScreenSetBufferEx's documentation, these need to be 0x100 aligned. */ void* tvBuffer = memalign(0x100, tvBufferSize); void* drcBuffer = memalign(0x100, drcBufferSize); /* Make sure the allocation actually succeeded! */ if (!tvBuffer || !drcBuffer) { WHBLogPrint("Out of memory!"); /* It's vital to free everything - under certain circumstances, your memory allocations can stay allocated even after you quit. */ if (tvBuffer) free(tvBuffer); if (drcBuffer) free(drcBuffer); /* Deinit everything */ OSScreenShutdown(); WHBProcShutdown(); WHBLogPrint("Quitting."); WHBLogCafeDeinit(); WHBLogUdpDeinit(); /* Your exit code doesn't really matter, though that may be changed in future. Don't use -3, that's reserved for HBL. */ return 1; } /* Buffers are all good, set them */ OSScreenSetBufferEx(SCREEN_TV, tvBuffer); OSScreenSetBufferEx(SCREEN_DRC, drcBuffer); /* Finally, enable OSScreen for each display! */ OSScreenEnableEx(SCREEN_TV, true); OSScreenEnableEx(SCREEN_DRC, true); /* WHBProcIsRunning will return false if the OS asks us to quit, so it's a good candidate for a loop */ VPADStatus status; VPADReadError error; VPADTouchData gamepadTouchScreen; bool vpad_fatal = false; uint32_t penColor = 0xFFFFFF00; while(WHBProcIsRunning()) { VPADRead(VPAD_CHAN_0, &status, 1, &error); switch (error) { case VPAD_READ_SUCCESS: { VPADGetTPCalibratedPoint(VPAD_CHAN_0, &gamepadTouchScreen, &status.tpNormal); break; } case VPAD_READ_NO_SAMPLES: { continue; } case VPAD_READ_INVALID_CONTROLLER: { WHBLogPrint("Gamepad disconnected!"); vpad_fatal = true; break; } default: { WHBLogPrintf("Unknown VPAD error! %08X", error); vpad_fatal = true; break; } } if (vpad_fatal) break; OSScreenPutFontEx(SCREEN_TV, 0, 0, "Simple Draw U (TV)."); OSScreenPutFontEx(SCREEN_DRC, 0, 0, "Simple Draw U (Gamepad)."); // clear screen if(status.trigger & VPAD_BUTTON_MINUS){ OSScreenClearBufferEx(SCREEN_TV, 0x00000000); OSScreenClearBufferEx(SCREEN_DRC, 0x00000000); } // select color if(status.trigger & VPAD_BUTTON_PLUS){ penColor = 0xFFFFFF00;} // white if(status.trigger & VPAD_BUTTON_A){ penColor = 0xBF5B5B00; } // red if(status.trigger & VPAD_BUTTON_B){ penColor = 0xC6B95500; } // yellow if(status.trigger & VPAD_BUTTON_X){ penColor = 0x3C8D8800; } // blue if(status.trigger & VPAD_BUTTON_Y){ penColor = 0x86B46000; } // green // draw on screen if(gamepadTouchScreen.touched){ OSScreenPutPixelEx(SCREEN_TV, gamepadTouchScreen.x-1, gamepadTouchScreen.y-1, penColor); OSScreenPutPixelEx(SCREEN_TV, gamepadTouchScreen.x+1, gamepadTouchScreen.y+1, penColor); OSScreenPutPixelEx(SCREEN_TV, gamepadTouchScreen.x, gamepadTouchScreen.y, penColor); OSScreenPutPixelEx(SCREEN_TV, gamepadTouchScreen.x-1, gamepadTouchScreen.y+1, penColor); OSScreenPutPixelEx(SCREEN_TV, gamepadTouchScreen.x+1, gamepadTouchScreen.y-1, penColor); OSScreenPutPixelEx(SCREEN_DRC, gamepadTouchScreen.x+1, gamepadTouchScreen.y+1, penColor); OSScreenPutPixelEx(SCREEN_DRC, gamepadTouchScreen.x-1, gamepadTouchScreen.y-1, penColor); OSScreenPutPixelEx(SCREEN_DRC, gamepadTouchScreen.x, gamepadTouchScreen.y, penColor); OSScreenPutPixelEx(SCREEN_DRC, gamepadTouchScreen.x-1, gamepadTouchScreen.y+1, penColor); OSScreenPutPixelEx(SCREEN_DRC, gamepadTouchScreen.x+1, gamepadTouchScreen.y-1, penColor); } /* Flush all caches - read the tutorial, please! */ DCFlushRange(tvBuffer, tvBufferSize); DCFlushRange(drcBuffer, drcBufferSize); /* Flip buffers - the text is now on screen! Flipping is kinda like committing your graphics changes. */ OSScreenFlipBuffersEx(SCREEN_TV); OSScreenFlipBuffersEx(SCREEN_DRC); } WHBLogPrint("Got shutdown request!"); /* It's vital to free everything - under certain circumstances, your memory allocations can stay allocated even after you quit. */ if (tvBuffer) free(tvBuffer); if (drcBuffer) free(drcBuffer); /* Deinit everything */ OSScreenShutdown(); WHBProcShutdown(); WHBLogPrint("Quitting."); WHBLogCafeDeinit(); /* Your exit code doesn't really matter, though that may be changed in future. Don't use -3, that's reserved for HBL. */ return 1; }