Advertisement
Kitomas

work for 2025-01-31 (2/4)

Jan 31st, 2025
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 28.21 KB | None | 0 0
  1. /******************************************************************************/
  2. /******************************************************************************/
  3. //"sokoban_and_kit32_2025-01-31\kit32\simulator\src\kit_32_cpu_syscall.cpp":
  4. #include <include_all.hpp>
  5.  
  6. #include <cmath> //for sqrtf, fmodf, and trig functions
  7.  
  8.  
  9.  
  10. kit::Mutex* ewatch_lock = nullptr;
  11.  
  12. namespace kit {
  13.  
  14. #define EWATCH_LOCK(_bool) if(ewatch_lock){ ewatch_lock->lock(_bool); }
  15.  
  16. static key32 key_queue[256];
  17.  
  18. static u8 key_read_index  = 0;
  19. static u8 key_write_index = 0;
  20.  
  21.  
  22.  
  23. static key32 key_queue_read(){
  24.   key32 key; //defaults to 0 (aka no event in queue)
  25.  
  26.   EWATCH_LOCK(true);
  27.   if(key_read_index != key_write_index){
  28.     key = key_queue[key_read_index++];
  29.   }
  30.   EWATCH_LOCK(false);
  31.  
  32.   return key;
  33.  
  34. }
  35.  
  36. static void key_queue_write(key32 key){
  37.   EWATCH_LOCK(true);
  38.   key_queue[key_write_index++] = key;
  39.  
  40.   //advance read index if last element was just overwritten
  41.   if(key_read_index == key_write_index)
  42.     ++key_read_index;
  43.  
  44.   EWATCH_LOCK(false);
  45.  
  46. }
  47.  
  48.  
  49.  
  50.  
  51.  
  52. #define r0  regs[0]
  53. #define r1  regs[1]
  54. #define r2  regs[2]
  55. #define r3  regs[3]
  56. #define r4  regs[4]
  57. #define r5  regs[5]
  58. #define sp  regs_sp
  59. #define flg regs_flags
  60. #define pc  regs_pc
  61.  
  62. void cpu32::syscall(u16 type){
  63.   switch(type){
  64.     case SYSCALL_TAN           : { r0.f32 = tanf(r0.f32); } break;
  65.     case SYSCALL_COSSIN        : { r1.f32 = sinf(r1.f32); } ATTR_FALLTHROUGH;
  66.     case SYSCALL_COS           : { r0.f32 = cosf(r0.f32); } break;
  67.     case SYSCALL_SIN           : { r1.f32 = sinf(r1.f32); } break;
  68.  
  69.     case SYSCALL_MEMSET        : { memory::set( ADDR(u8,r0.u32),           r1.u8, r2.u32); } break;
  70.     case SYSCALL_MEMCPY        : { memory::copy(ADDR(u8,r0.u32), ADDR(u8,r1.u32), r2.u32); } break;
  71.  
  72.     case SYSCALL_SETDRAWCOLOR  : { rndr->setDrawColor(r0.u32); } break;
  73.  
  74.     case SYSCALL_DRAWPOINT_S32 : { rndr->drawPoint(r0.s32, r1.s32); } break;
  75.     case SYSCALL_DRAWPOINT_F32 : { rndr->drawPoint(r0.f32, r1.f32); } break;
  76.     case SYSCALL_DRAWLINE_S32  : { rndr->drawLine(r0.s32, r1.s32, r2.s32, r3.s32); } break;
  77.     case SYSCALL_DRAWLINE_F32  : { rndr->drawLine(r0.f32, r1.f32, r2.f32, r3.f32); } break;
  78.     case SYSCALL_DRAWRECT_S32  : { rndr->drawRects((shape::rect *)regs, 1); } break;
  79.     case SYSCALL_DRAWRECT_F32  : { rndr->drawRects((shape::frect*)regs, 1); } break;
  80.     case SYSCALL_FILLRECT_S32  : { rndr->fillRects((shape::rect *)regs, 1); } break;
  81.     case SYSCALL_FILLRECT_F32  : { rndr->fillRects((shape::frect*)regs, 1); } break;
  82.  
  83.     #define drawXs(_call, _shp) \
  84.       rndr->_call(ADDR(shape::_shp, r0.u32), r1.u32&KIT_S32_MAX)
  85.     case SYSCALL_DRAWPOINTS_S32: { drawXs(drawPoints, point); } break;
  86.     case SYSCALL_DRAWPOINTS_F32: { drawXs(drawPoints,fpoint); } break;
  87.     case SYSCALL_DRAWLINES_S32 : { drawXs(drawLines , point); } break;
  88.     case SYSCALL_DRAWLINES_F32 : { drawXs(drawLines ,fpoint); } break;
  89.     case SYSCALL_DRAWRECTS_S32 : { drawXs(drawRects , rect ); } break;
  90.     case SYSCALL_DRAWRECTS_F32 : { drawXs(drawRects ,frect ); } break;
  91.     case SYSCALL_FILLRECTS_S32 : { drawXs(fillRects , rect ); } break;
  92.     case SYSCALL_FILLRECTS_F32 : { drawXs(fillRects ,frect ); } break;
  93.  
  94.     case SYSCALL_CLEAR         : { rndr->clear(); } break;
  95.     case SYSCALL_PRESENT       : {
  96.       rndr->present();
  97.  
  98.       u64 ticksEnd    = time::getTicks();
  99.       s64 ticksDelta  = ticksEnd-ticksStart;
  100.       f64 timeDelta   = (f64)ticksDelta/time::getTicksPerSecond();
  101.       s32 timeDeltaMS = (s32)(timeDelta*1000.0f);
  102.  
  103.       u32 timeToSleepMS = MAX(16-timeDeltaMS, 1);
  104.       time::sleep(timeToSleepMS);
  105.  
  106.       ticksStart = time::getTicks();
  107.  
  108.     } break;
  109.  
  110.     case SYSCALL_RAND_U8       : { r0.u8  = (u8 )(frandf_b()*KIT_U8_MAX ); } break;
  111.     case SYSCALL_RAND_U16      : { r0.u16 = (u16)(frandf_b()*KIT_U16_MAX); } break;
  112.     case SYSCALL_RAND_U32      : { r0.u32 = (u32)(frandf()  *KIT_U32_MAX); } break;
  113.     case SYSCALL_RAND_F32      : { r0.f32 = frandf();                      } break;
  114.  
  115.     case SYSCALL_GETKEY        : { r0.u32 = key_queue_read().value; } break;
  116.  
  117.     case SYSCALL_DRAWTEXT      : {
  118.       text->draw(r0.s32, r1.s32, ADDR(char,r2.u32), r3.u32&KIT_S32_MAX);
  119.     } break;
  120.  
  121.     default:;
  122.   }
  123.  
  124. }
  125.  
  126.  
  127.  
  128.  
  129.  
  130. }; /* namespace kit */
  131.  
  132. using namespace kit;
  133.  
  134.  
  135.  
  136.  
  137.  
  138. void ewatch_func(Event& evt, void* userdata){
  139.   if(KIT_EVENT_ID(evt.type) != KEVENT_KEY) return;
  140.  
  141.   key32 key = convert_key(evt.key);
  142.   key_queue_write(key);
  143.  
  144.   (void)userdata;
  145.  
  146. }
  147.  
  148. /******************************************************************************/
  149. /******************************************************************************/
  150. //"sokoban_and_kit32_2025-01-31\kit32\simulator\src\main.cpp":
  151. #include <include_all.hpp>
  152.  
  153. #include <unistd.h> //for getcwd()
  154. #include <cstdlib> //for std::srand & std::rand
  155.  
  156. #if RAND_MAX > 32767
  157. #error "RAND_MAX > 32767; frand should be altered to accomodate"
  158. #endif
  159.  
  160.  
  161. using namespace kit;
  162.  
  163.  
  164. /******************************************************************************/
  165.  
  166.  
  167. Window*        wndw = nullptr;
  168. Renderer*      rndr = nullptr;
  169. BFont_Texture* text = nullptr;
  170. BFont_Texture* textColored[16] = {0};
  171.  
  172.  
  173. /****************************** "callbacks.cpp" *******************************/
  174.  
  175.  
  176. s32 cb_audio(void* _dst, const AudioDeviceInfo& info);
  177.  
  178. extern AudioDevice* audio;
  179. extern bool  audioIsReady;
  180.  
  181.  
  182. /******************************************************************************/
  183.  
  184.  
  185. //assumes RAND_MAX is 32767
  186. #define GET_FRAND_VALUE(cast) ( (cast)(std::rand()<<15|std::rand())/0x3FFFFFFF )
  187.  
  188. f64 frand  (){  return GET_FRAND_VALUE(f64);              } // 0.0f -> 1.0f
  189. f64 frand2 (){  return GET_FRAND_VALUE(f64)*2.0f - 1.0f;  } //-1.0f -> 1.0f
  190. f32 frandf (){  return GET_FRAND_VALUE(f32);              } // 0.0f -> 1.0f
  191. f32 frandf2(){  return GET_FRAND_VALUE(f32)*2.0f - 1.0f;  } //-1.0f -> 1.0f
  192.  
  193. f32 frandf_b (){ return  (f32)std::rand()/RAND_MAX;               }
  194. f32 frandf2_b(){ return ((f32)std::rand()/RAND_MAX)*2.0f - 1.0f;  }
  195.  
  196.  
  197. /******************************************************************************/
  198.  
  199.  
  200.  
  201.  
  202.  
  203. #define PREVENT_RUNNING_WHILE_ZIPPED 1
  204.  
  205. int user_main(int argc, char** argv);
  206.  
  207. int main(int argc, char** argv){  int returnStatus = -1;  try {
  208.   u64 timeDelta, timeStartAudio, timeStartAll = time::getMS();
  209.  
  210. #if PREVENT_RUNNING_WHILE_ZIPPED == 1
  211. if(!(argc >= 2  &&  argv[1][0] == '/')){
  212.   //this should hopefully prevent people from executing the program
  213.    //before it's unzipped (in most cases, at least)
  214.   #define EXTRACT_MSG "This program must be ran normally, after being unzipped"
  215.   char cwd[256];
  216.   getcwd(cwd, sizeof(cwd));
  217.   cwd[255] = 0; //just in case
  218.   u32 lastChar = strnLen(cwd)-1;
  219.   if(cwd[lastChar]=='/' || cwd[lastChar]=='\\') cwd[lastChar] = 0;
  220.  
  221.   //first check
  222.   //checks if the program's current working directory is
  223.    //"C:\Users\<name>\AppData" (specific to windows)
  224.   #if defined(_WIN32)
  225.   {
  226.     u32 i = 0,  backSlashCount = 0;
  227.     bool foundUsers = false;
  228.  
  229.     if((cwd[0]|32) == 'c') //(x|32 makes the char x lowercase)
  230.     for(; i<256; ++i){ _start:
  231.  
  232.       if(cwd[i] == '\0') break;
  233.       if(cwd[i] == '\\') ++backSlashCount;
  234.  
  235.       if(backSlashCount == 1){
  236.         if(!strnCmp("Users", &cwd[++i], 5)) foundUsers = true;
  237.         goto _start; //++i should only occur once this iteration
  238.  
  239.       }
  240.  
  241.       if(foundUsers  &&  backSlashCount == 3){
  242.         if(!strnCmp("AppData", &cwd[++i], 7)) throw EXTRACT_MSG;
  243.         break;
  244.  
  245.       }
  246.  
  247.     }
  248.  
  249.   }
  250.   #endif /* defined(_WIN32) */
  251.  
  252.   //second check
  253.   //all this does is it clips the executable name from the
  254.    //full path (argv[0]) to compare it to the current working directory
  255.   //(this should work even if argv[0] is something else,
  256.    //since you're supposed to run this program normally anyway)
  257.   if(argc > 0){
  258.     char*  path     = argv[0];
  259.     size_t path_len = strnLen(path);
  260.     s32    i        = path_len-1;
  261.     bool   fwdSlash = false;
  262.  
  263.     if(path_len < 256)
  264.     for(; i>=0; --i){
  265.       fwdSlash = path[i]=='/';
  266.       if(fwdSlash  ||  path[i] == '\\'){ path[i] = 0; break; }
  267.     }
  268.  
  269.     if(i >= 0){
  270.       //throw if the paths are different
  271.       if(strnCmp(path, cwd)) throw EXTRACT_MSG;
  272.       //put slash back in case user wants to reference argv[0] too
  273.       path[i] = (fwdSlash) ? '/' : '\\';
  274.     }
  275.  
  276.   }
  277. }
  278. #endif /* PREVENT_RUNNING_WHILE_ZIPPED == 1 */
  279.  
  280.   initSubsystems(KINIT_EVERYTHING);
  281.  
  282. /********************************* AUDIO INIT *********************************/
  283.  
  284.   AudioDeviceInfo audio_info = audiofunc::getDefaultDevInfo();
  285.   audio_info.sampleFormat = SMPFMT_F32;
  286.   audio_info.numChannels  = 2;
  287.   audio_info.zeroBuffer   = true;
  288.   audio_info.callback     = cb_audio;
  289.   audio_info.userdata     = nullptr;
  290.  
  291.   //actually, for some reason setting audio_info's sampleRate to be lower
  292.    //than 15701 causes _audio.pause() to hang indefinitely (for me at least)
  293.   //tbd: figure out why this happens
  294.   audio_info.sampleRate = MAX(audio_info.sampleRate, 15701);
  295.  
  296.   AudioDevice _audio(nullptr, audio_info, false);  audio = &_audio;
  297.   _audio.play(); //begin fading in audio
  298.   timeStartAudio = time::getMS();
  299.  
  300.   //...
  301.  
  302. /********************************* VIDEO INIT *********************************/
  303.  
  304.   audioIsReady = true;
  305.  
  306. { //<- closes at the end of video cleanup
  307.  
  308.   Window _wndw(WIN_TITLE, WIN_W, WIN_H, WIN_FLAGS|WINFLAG_HIDDEN);  wndw=&_wndw;
  309.  
  310.   Renderer _rndr(_wndw);  rndr = &_rndr;
  311.  
  312.   #define GRAY(_hexvalue) 0xFF##_hexvalue##_hexvalue##_hexvalue
  313.   BFont_Texture _text(_rndr, nullptr, nullptr, GRAY(FF), 16384);  text = &_text;
  314.  
  315.   const clrs::ABGR textColored_colors[TEXTCOLORED_LEN] = {
  316.     0xFF000000, //gray0 (  0)
  317.     0xFF555555, //gray1 ( 85)
  318.     0xFFAAAAAA, //gray2 (170)
  319.     0xFFFFFFFF, //gray3 (255)
  320.     0xFF000080, //redLo
  321.     0xFF0000FF, //redHi
  322.     0xFF008000, //greenLo
  323.     0xFF00FF00, //greenHi
  324.     0xFF800000, //blueLo
  325.     0xFFFF0000, //blueHi
  326.     0xFF808000, //cyanLo
  327.     0xFFFFFF00, //cyanHi
  328.     0xFF800080, //magentaLo
  329.     0xFFFF00FF, //magentaHi
  330.     0xFF008080, //yellowLo
  331.     0xFF00FFFF, //yellowHi
  332.   };
  333.  
  334.   for(u32 i=0; i<TEXTCOLORED_LEN; ++i){
  335.     textColored[i] = new BFont_Texture(_rndr, nullptr, nullptr,
  336.                                        textColored_colors[i], 1024);
  337.   }
  338.  
  339.   //...
  340.  
  341. /********************************* USER MAIN **********************************/
  342.  
  343.   timeDelta = time::getMS()-timeStartAll;
  344.   kit_LogInfo("Initialized in %llums", timeDelta);
  345.  
  346.   //audio's actual fade DELAY is 90ms, whereas the fade in after that is 10ms.
  347.    //so 95 should put the audio at about halfway through the fade in
  348.   timeDelta = time::getMS()-timeStartAudio;
  349.   time::sleep((u32)MAX((s64)(95-timeDelta), 1));
  350.  
  351.   //_wndw.setVisibility(true); //this is generally done by the user
  352.   std::srand((u32)time::getTicks());
  353.   returnStatus = user_main(argc, argv);
  354.   _wndw.setVisibility(false);
  355.  
  356.   _audio.pause(); //begin fading out audio
  357.  
  358. /******************************* VIDEO CLEANUP ********************************/
  359.  
  360. {
  361.  
  362.   //...
  363.  
  364. }
  365.  
  366.   for(u32 i=0; i<TEXTCOLORED_LEN; ++i) NULLDELETE(textColored[i],BFont_Texture);
  367.  
  368. } //garbage collect video init stuff
  369.  
  370. /******************************* AUDIO CLEANUP ********************************/
  371.  
  372.   //audio's actual fadeout is 10ms, so waiting ~12ms total should be enough
  373.   while(_audio.isPlaying()) time::sleep(4);
  374.   _audio.lock(); //just in case
  375.  
  376. {
  377.  
  378.   //...
  379.  
  380. }
  381.  
  382.   _audio.unlock();
  383.  
  384. /************************** CATCH EXCEPTION OR EXIT ***************************/
  385.  
  386. } catch(const char* errorText){
  387.   #ifdef _DEBUG
  388.     kit_LogError("FATAL EXCEPTION OCCURRED: \"%s\"\n", errorText);
  389.   #else
  390.     showMsgBox(errorText, "FATAL EXCEPTION OCCURRED!", MSGBOX_ERROR);
  391.   #endif /* _DEBUG */
  392.   //redundant, as quitSubsystems already does this when given KINIT_EVERYTHING
  393.   //freeThreadErrors();
  394.  
  395. }
  396.  
  397.   //can't error, and is also safe to call even if no subsystems are active!
  398.   quitSubsystems(KINIT_EVERYTHING);
  399.  
  400.   //a nonzero value indicates a memory leak!
  401.   if(memory::getNumAllocations())
  402.     kit_LogWarn("# OF ALLOCATIONS = %llu", memory::getNumAllocations());
  403.  
  404.   return returnStatus;
  405.  
  406. }
  407. /******************************************************************************/
  408. /******************************************************************************/
  409. //"sokoban_and_kit32_2025-01-31\kit32\simulator\src\user_main.cpp":
  410. #include <include_all.hpp>
  411.  
  412. //begone, unused parameter warning
  413. #define UM_RETURN(_val) { (void)argc, (void)argv; return (_val); }
  414.  
  415.  
  416. using namespace kit;
  417.  
  418.  
  419.  
  420.  
  421.  
  422. /*
  423. void ewatch_func(Event& evt, void* userdata){
  424.   switch(evt.type){
  425.     case KEVENT_KEY
  426.   }
  427.  
  428. }
  429. */
  430.  
  431.  
  432. cpu32 cpu;
  433.  
  434.  
  435.  
  436.  
  437.  
  438. shape::point windowSize(WIN_W, WIN_H);
  439.  
  440. bool handleEvents(){
  441.   bool run = true;
  442.  
  443.   Event evt;
  444.   while(pollEvent(&evt))
  445.   switch(evt.type){
  446.     case KEVENT_QUIT: run = false; break;
  447.     /*
  448.     case KEVENT_KEY_DOWN: {
  449.       bool size_changed = false;
  450.  
  451.       if(evt.key.vkey == VKEY_F11){
  452.         windowSize.x = MAX(windowSize.x-LOGI_W, LOGI_W);
  453.         windowSize.y = MAX(windowSize.y-LOGI_H, LOGI_H);
  454.         size_changed = true;
  455.       } else if(evt.key.vkey == VKEY_F12  &&  !evt.key.repeat){
  456.         windowSize += {LOGI_W, LOGI_H};
  457.         size_changed = true;
  458.       }
  459.  
  460.       if(size_changed) wndw->setSize(windowSize.x, windowSize.y);
  461.     } break;
  462.     */
  463.     default:;
  464.   }
  465.  
  466.   return run;
  467.  
  468. }
  469.  
  470.  
  471.  
  472.  
  473.  
  474. char msgbox_buffer[512];
  475.  
  476. void cpu_msgbox(){
  477.   snPrintf(msgbox_buffer, sizeof(msgbox_buffer),
  478. "\
  479. r0=%f, r1=%f, r2=%f, r3=%f, r4=%f, r5=%f\n\n\
  480. r0=0x%08X, r1=0x%08X, r2=0x%08X, r3=0x%08X, r4=0x%08X, r5=0x%08X\n\n\
  481. sp=0x%08X, flg=0b%08X, pc=0x%08X\
  482. ",
  483.   cpu.regs[0].f32, cpu.regs[1].f32, cpu.regs[2].f32, cpu.regs[3].f32, cpu.regs[4].f32, cpu.regs[5].f32,
  484.   cpu.regs[0].u32, cpu.regs[1].u32, cpu.regs[2].u32, cpu.regs[3].u32, cpu.regs[4].u32, cpu.regs[5].u32,
  485.   cpu.regs_sp.u32, bin_hex(cpu.regs_flags.u8), cpu.regs_pc
  486. );
  487.  
  488.   showMsgBox(msgbox_buffer, "cpu state:");
  489.  
  490. }
  491.  
  492.  
  493.  
  494.  
  495.  
  496. extern Mutex* ewatch_lock;
  497.  
  498. void ewatch_func(Event& evt, void* userdata);
  499.  
  500. int user_main(int argc, char** argv){
  501.   BinaryData prgData("prg.bin");
  502.   if(prgData.getSize() > MEMSIZEh)
  503.     throw "input file size out of bounds";
  504.  
  505.   memory::WrapperSIMD memory(MEMSIZE+256);
  506.   memory::set(memory.ptr, 0, MEMSIZE);
  507.   memory::copy(memory.ptr, prgData.getData(), prgData.getSize());
  508.  
  509.   #define PERSISTENT_NAME "persistent_memory.bin"
  510.   if(fileio::exists(PERSISTENT_NAME)){
  511.     BinaryData persistentData(PERSISTENT_NAME);
  512.     memory::copy(((u8*)memory.ptr)+MEMSIZEh,
  513.                  persistentData.getData(),
  514.                  MIN(persistentData.getSize(),MEMSIZEh));
  515.   }
  516.  
  517.   cpu.memory = (u8*)memory.ptr;
  518.  
  519.  
  520.  
  521.   ewatch_lock = new Mutex;
  522.   EventWatch ewatch(ewatch_func, ewatch_lock);
  523.  
  524.  
  525.  
  526.   rndr->setLogicalSize(LOGI_W, LOGI_H);
  527.   wndw->setMinSize(LOGI_W, LOGI_H);
  528.   wndw->setVisibility(true);
  529.  
  530.   while(true){
  531.     if(!handleEvents()) break;
  532.     if(cpu.execute() == EXERES_BRK) cpu_msgbox();
  533.   }
  534.  
  535.  
  536.  
  537.   NULLDELETE(ewatch_lock, Mutex);
  538.  
  539.   wndw->setVisibility(false);
  540.  
  541.   fileio::writeAll(PERSISTENT_NAME, ((u8*)memory.ptr)+MEMSIZEh, MEMSIZEh);
  542.  
  543.   UM_RETURN(0);
  544.  
  545. }
  546. /******************************************************************************/
  547. /******************************************************************************/
  548. //"sokoban_and_kit32_2025-01-31\kit32\simulator\src\utils_core.cpp":
  549. #include <include_all.hpp>
  550.  
  551.  
  552. using namespace kit;
  553.  
  554.  
  555.  
  556.  
  557.  
  558. /******************************************************************************/
  559. /******************************************************************************/
  560. //"sokoban_and_kit32_2025-01-31\sokoban\src\callbacks.cpp":
  561. #include <include_all.hpp>
  562.  
  563. using namespace kit;
  564.  
  565.  
  566.  
  567.  
  568.  
  569. void cb_music_fade_in(void* userdata_a, void* userdata_b);
  570. void cb_music_fade_out(void* userdata_a, void* userdata_b);
  571.  
  572. AudioDevice* audio = nullptr;
  573. bool  audioIsReady = false;
  574.  
  575. SoundEngine* sfx = nullptr;
  576.  
  577. s32         music_index      = -1;
  578. Xmp*        music            = nullptr;
  579. Stereo_s16* music_buffer_src = nullptr;
  580. Stereo_f32* music_buffer_dst = nullptr;
  581. AudioFade   music_fade       = {cb_music_fade_in, cb_music_fade_out};
  582.  
  583.  
  584.  
  585.  
  586.  
  587. struct music_id_t { u32 name_index, pos = 0; }; //8B
  588.  
  589. #define MUSIC_NAME_musicbox1 0
  590.  
  591. #define MUSIC_NAME_PREFIX "dat/music/"
  592.  
  593. static const char* music_names[] = {
  594.   MUSIC_NAME_PREFIX "musicbox1_v2.xm",
  595. };
  596.  
  597. #define MUSIC_IDS_LEN countof(music_ids, music_id_t)
  598.  
  599. static music_id_t music_ids[] = {
  600.   {MUSIC_NAME_musicbox1, 0}, //plays upon running the game
  601.   {MUSIC_NAME_musicbox1, 2}, //plays after returning from a menu
  602. };
  603.  
  604.  
  605.  
  606.  
  607.  
  608. bool music_playing = false;
  609.  
  610. void cb_music_fade_in(void* userdata_a, void* userdata_b){
  611.   u32 sampleRate = (u32)(u64)userdata_a; //lol
  612.   (void)userdata_b;
  613.  
  614.   if(!sampleRate  ||  !music  ||  music_index < 0){
  615.     music_fade.fadeIn = false;
  616.     return;
  617.   }
  618.  
  619.   if((u32)music_index >= MUSIC_IDS_LEN){ kit_LogError("music_index >= MUSIC_IDS_LEN"); return; }
  620.  
  621.   music_id_t id = music_ids[music_index];
  622.   const char* name = music_names[id.name_index];
  623.  
  624.   if(name == nullptr){ kit_LogError("music name = nullptr"); return; }
  625.   if(!fileio::exists(name)){ kit_LogError("music module \"%s\" doesn't exist", name); return; }
  626.  
  627.   s32 result = music->moduleLoad(name);
  628.   if(result){ kit_LogError("failed to load music module \"%s\": code = %i", name, result); return; }
  629.  
  630.   result = music->playerStart(sampleRate);
  631.   if(result){ kit_LogError("failed to start music player: code = %i", result); return; }
  632.  
  633.   music->setPlayerPosition(id.pos);
  634.  
  635.   music_playing = true;
  636.  
  637. }
  638.  
  639.  
  640.  
  641.  
  642.  
  643. void cb_music_fade_out(void* userdata_a, void* userdata_b){
  644.   (void)userdata_a;
  645.   (void)userdata_b;
  646.  
  647.   if(!music) return;
  648.  
  649.   music->moduleStop();
  650.   music->moduleRelease();
  651.   music->playerEnd();
  652.  
  653.   if(music_index >= 0) music_fade.fadeIn = true;
  654.  
  655.   music_playing = false;
  656.  
  657. }
  658.  
  659.  
  660.  
  661.  
  662.  
  663. #define src music_buffer_src
  664. #define dst music_buffer_dst
  665.  
  666. static f32 music_vol_old = 0.0f;
  667.  
  668. static s32 cb_music_thread(void* userdata){
  669.   s32 result = 0;
  670.  
  671.   u32 dst_len  = (u32)(u64)userdata; //lol
  672.   u32 dst_size = dst_len*sizeof(Stereo_f32);
  673.   u32 src_size = dst_len*sizeof(Stereo_s16);
  674.  
  675.  
  676.   if(!music || !src || !dst){
  677.     result = -KIT_XMP_ERROR_STATE; _err:
  678.     if(dst) memory::set(dst, 0, dst_size);
  679.     return result;
  680.  
  681.   }
  682.  
  683.  
  684.   f32       t     = 0.0f;
  685.   const f32 t_inc = 1.0f/dst_len;
  686.  
  687.   if(music_playing){
  688.     result = music->playBuffer(src, src_size, true);
  689.     if(result) goto _err;
  690.  
  691.     //no need to multiply at all
  692.     if(music_vol_old==1.0f && settings.music_vol==1.0f){
  693.       for(u32 i=0; i<dst_len; ++i){
  694.         dst[i].l = ((f32)src[i].l/32768);
  695.         dst[i].r = ((f32)src[i].r/32768);
  696.       }
  697.  
  698.     //no need to interpolate
  699.     } else if(music_vol_old == settings.music_vol){
  700.       for(u32 i=0; i<dst_len; ++i){
  701.         dst[i].l = ((f32)src[i].l/32768) * settings.music_vol;
  702.         dst[i].r = ((f32)src[i].r/32768) * settings.music_vol;
  703.       }
  704.  
  705.     //must interpolate between old and new
  706.     } else {
  707.       for(u32 i=0; i<dst_len; ++i){
  708.         f32 volume = LERP2(music_vol_old, settings.music_vol, t);
  709.         dst[i].l = ((f32)src[i].l/32768) * volume;
  710.         dst[i].r = ((f32)src[i].r/32768) * volume;
  711.         t += t_inc;
  712.       }
  713.  
  714.     }
  715.  
  716.     music_vol_old = settings.music_vol;
  717.  
  718.   } else { //no music is playing; set music buffer to 0
  719.     memory::set(dst, 0, dst_size);
  720.  
  721.   }
  722.  
  723.  
  724.   if(music_index < 0) music_fade.fadeIn = false;
  725.   music_fade.applyFade(&dst->l, dst_len*2, 2);
  726.  
  727.   return result;
  728.  
  729. }
  730.  
  731. #undef src
  732. #undef dst
  733.  
  734.  
  735.  
  736.  
  737.  
  738. s32 cb_audio(void* _dst, const AudioDeviceInfo& info){
  739.   //music_buffer_src is the first thing to be freed in the 'audio cleanup'
  740.    //portion of main(), so if it == nullptr, that means audio is in
  741.    //the middle of being uninitialized
  742.    //(that, or music_buffer_src simply hasn't been set yet,
  743.    // in which case it should exit early anyway)
  744.   if(!audioIsReady  ||  music_buffer_src == nullptr) return 0;
  745.  
  746.   Stereo_f32* dst     = (Stereo_f32*)_dst;
  747.   u16         dst_len = info.sampleFrames;
  748.  
  749.   //process music in a separate thread...
  750.   Thread music_thread(cb_music_thread, (void*)(u64)dst_len, true, 0, "music");
  751.  
  752.   //mix whatever sound effects that may be actively playing
  753.   if(sfx) sfx->mixTracks(dst, dst_len, info.timeStartMS);
  754.  
  755.   s32 result = music_thread.waitUntilDone();
  756.   if(result && result != -999) kit_LogError("music thread returned %i", result);
  757.  
  758.   for(u16 i=0; i<dst_len; ++i){
  759.     //...before mixing its output into dst
  760.      //(+= instead of =, since sfx has already mixed its own output into dst)
  761.     dst[i].l += music_buffer_dst[i].l;
  762.     dst[i].r += music_buffer_dst[i].r;
  763.  
  764.     //finally, clamp the samples so that they aren't out of bounds
  765.     dst[i].l = CLAMP(dst[i].l, -1.0f, 1.0f);
  766.     dst[i].r = CLAMP(dst[i].r, -1.0f, 1.0f);
  767.  
  768.   }
  769.  
  770.   return 0;
  771.  
  772. }
  773. /******************************************************************************/
  774. /******************************************************************************/
  775. //"sokoban_and_kit32_2025-01-31\sokoban\src\ctx_lvl_editor.cpp":
  776. #include <include_all.hpp>
  777.  
  778.  
  779. using namespace kit;
  780.  
  781.  
  782.  
  783.  
  784.  
  785. static struct {
  786.   bool init  = false;
  787. } ctx;
  788.  
  789. static inline void reset_ctx(){
  790.   if(ctx.init) return;
  791.  
  792.   memory::set(&ctx, 0, sizeof(ctx));
  793.  
  794.   cursor_scroll = true;
  795.   cursor_snow   = false;
  796.  
  797. }
  798.  
  799.  
  800.  
  801.  
  802.  
  803.  
  804.  
  805. s32 ctx_lvl_editor_evt(){
  806.   reset_ctx();
  807.  
  808.   Event evt; bool run = true;
  809.  
  810.   return 0;
  811. }
  812.  
  813.  
  814.  
  815.  
  816.  
  817. void ctx_lvl_editor_draw(){
  818.  
  819. }
  820. /******************************************************************************/
  821. /******************************************************************************/
  822. //"sokoban_and_kit32_2025-01-31\sokoban\src\ctx_lvl_select.cpp":
  823. #include <include_all.hpp>
  824.  
  825.  
  826. using namespace kit;
  827.  
  828.  
  829.  
  830.  
  831.  
  832. enum mouse_zone_names {
  833.   MZONE_SLIDER,
  834.   MZONE_BACK,
  835.   MZONE_UP,
  836.   MZONE_DOWN,
  837.   MZONE_PLAY,
  838.   MZONE_COUNT,
  839. };
  840.  
  841.  
  842.  
  843.  
  844.  
  845. #define LEVELS_PATH "."
  846. #define UV_STEP(_amount) ((1.0f/ICON_MENU_LEN)*(_amount))
  847.  
  848. #define FILENAME(_n)   ctx.names->files[_n]
  849. #define FILENAME_C(_n) FILENAME(_n)->c_str()
  850. #define FILENAMES_LEN  ctx.names->files_len
  851.  
  852. #define TEXT_SCALE (1)
  853. #define MAX_LEN ( (LOGI_W-LOGI_H-32)/(8*TEXT_SCALE) )
  854. #define MAX_NAMES ( (LOGI_H/(8*TEXT_SCALE)) )
  855.  
  856. static struct {
  857.   file_list* names = nullptr;
  858.   s32        opt   = -1;
  859.   bool       hover[MZONE_COUNT];
  860.   bool       init  = false;
  861. } ctx;
  862.  
  863. #define destroy_filenames() NULLDELETE(ctx.names, file_list)
  864.  
  865. static bool query_level_directory(){
  866.   destroy_filenames();
  867.   ctx.names = new file_list(LEVELS_PATH);
  868.   return FILENAMES_LEN != 0;
  869.  
  870. }
  871.  
  872. #define SELECT(_newstate) \
  873.   settings.selected = CLAMP((_newstate), 0, (s32)FILENAMES_LEN-1)
  874. #define SELECT_REL(_diff) \
  875.   SELECT(settings.selected+(_diff))
  876.  
  877. static inline void reset_ctx(){
  878.   if(ctx.init) return;
  879.  
  880.   music_play(-1);
  881.  
  882.   destroy_filenames(); //just in case
  883.  
  884.   memory::set(&ctx, 0, sizeof(ctx));
  885.  
  886.   query_level_directory();
  887.  
  888.   ctx.opt = -1;
  889.  
  890.   settings.selected = CLAMP(settings.selected,
  891.                             0, FILENAMES_LEN-1);
  892.  
  893.   ctx.init = true;
  894.  
  895.  
  896.   cursor_scroll = false;
  897.   cursor_snow   = false;
  898.   clear_snowflakes();
  899.  
  900. }
  901.  
  902.  
  903.  
  904.  
  905.  
  906. #define MOUSE_ZONES_LEN countof(mouse_zones, shape::rect)
  907.  
  908. static shape::rect mouse_zones[] = {
  909.   {        0,        63, 32, LOGI_H+1-3*32}, //slider
  910.   {        0,         0, 32,            31}, //back
  911.   {        0,        31, 32,            32}, //up
  912.   {        0, LOGI_H-32, 32,            32}, //down
  913.   {LOGI_W-32, LOGI_H-32, 32,            32}, //play
  914.  
  915. };
  916.  
  917.  
  918.  
  919.  
  920.  
  921. s32 ctx_lvl_select_evt(){
  922.   reset_ctx();
  923.  
  924.   Event evt; bool run = true;
  925.  
  926.   #define WAS_MOUSE_DOWN (mouseClick && !mouseDrag)
  927.   #define OPT_CHANGED (ctx.opt != opt_old  &&  ctx.opt != -1)
  928.   bool mouseDrag  = true;
  929.   bool mouseClick = false;
  930.   s32 opt_old       = ctx.opt;
  931.   u32 ctx_which_old = ctx_which;
  932.  
  933.  
  934.  
  935.   if(ctx.names->files_len == 0){
  936.     while(pollEvent(&evt) && run){
  937.       if(evt.type == KEVENT_KEY_DOWN ||
  938.          evt.type == KEVENT_MOUSE_DOWN)
  939.       {
  940.         ctx_which = CTX_MAIN_MENU;
  941.         music_play(-2);
  942.       }
  943.       run = default_event_handler(evt);
  944.     }
  945.  
  946.  
  947.   } else while(pollEvent(&evt) && run)
  948.   switch(evt.type){
  949.     case KEVENT_MOUSE_DOWN: mouseDrag = false; ATTR_FALLTHROUGH;
  950.     case KEVENT_MOUSE_MOVED: {
  951.       mouseClick = evt.mouse.button!=0;
  952.       ctx.opt = -1;
  953.  
  954.       for(u32 i=0; i<MOUSE_ZONES_LEN; ++i){
  955.         shape::point pos = {evt.mouse.x, evt.mouse.y};
  956.         if(point_in_rect(pos, mouse_zones[i])){
  957.           if(opt_old != (s32)i){
  958.  
  959.           }
  960.           ctx.opt = i; break;
  961.  
  962.         }
  963.  
  964.       }
  965.     } goto _def_evt;
  966.     case KEVENT_MOUSE_WHEEL: {
  967.       SELECT_REL(-evt.mouse.dy);
  968.     } goto _def_evt;
  969.     default: _def_evt: run = default_event_handler(evt);
  970.  
  971.   }
  972.  
  973.  
  974.  
  975.   memory::set(ctx.hover, 0, sizeof(ctx.hover));
  976.   if(ctx.opt >= 0) ctx.hover[ctx.opt] = true;
  977.  
  978.   if     (ctx.opt>=MZONE_BACK && OPT_CHANGED   ) SFXPLAY(SFXNAME_BLIP1, 1,1.2);
  979.   else if(ctx.opt!=-1         && WAS_MOUSE_DOWN) SFXPLAY(SFXNAME_CHK1 , 1,1.0);
  980.  
  981.   switch(ctx.opt){
  982.     case MZONE_UP  : if(WAS_MOUSE_DOWN){ SELECT_REL(-1); } break;
  983.     case MZONE_DOWN: if(WAS_MOUSE_DOWN){ SELECT_REL( 1); } break;
  984.     case MZONE_BACK: if(WAS_MOUSE_DOWN){
  985.       ctx_which = CTX_MAIN_MENU;
  986.       music_play(-2);
  987.     } break;
  988.  
  989.     case MZONE_PLAY: {
  990.       //tbd
  991.     } break;
  992.  
  993.     case MZONE_SLIDER: if(mouseClick){
  994.       s32 adjusted = cursor_pos.y-mouse_zones[MZONE_SLIDER].y;
  995.       f32 percent  = (f32)adjusted/mouse_zones[MZONE_SLIDER].h;
  996.       SELECT( (s32)(((FILENAMES_LEN-1)*percent)+0.5f) );
  997.     } break;
  998.  
  999.     default:;
  1000.  
  1001.   }
  1002.  
  1003.  
  1004.  
  1005.  
  1006.   if(!run  ||  ctx_which_old != ctx_which){
  1007.     destroy_filenames();
  1008.     ctx.init = false;
  1009.     return -run; //will return -1 unless run==0
  1010.   }
  1011.  
  1012.   return run;
  1013.  
  1014. }
  1015.  
  1016.  
  1017.  
  1018.  
  1019.  
  1020. #define RIGHT_EDGE (31+8*(TEXT_SCALE)*(MAX_LEN))
  1021. #define TEXT_BASE_Y (  (LOGI_H/2 - (8*(TEXT_SCALE))/2)  )
  1022.  
  1023. void ctx_lvl_select_draw(){
  1024.   if(FILENAMES_LEN == 0){
  1025.     text->scale = {3,3};
  1026.     text->drawBox(KIT_CENTER_TEXT, KIT_CENTER_TEXT,
  1027.                   "no levels found!");
  1028.     return;
  1029.   }
  1030.  
  1031.  
  1032.  
  1033.   rndr->setDrawColor(GRAY(00));
  1034.  
  1035.   shape::rect drawrect = {0,0, RIGHT_EDGE,LOGI_H};
  1036.   rndr->fillRects(&drawrect);
  1037.  
  1038.   drawrect = {LOGI_W-32, LOGI_H-32, 32, 32};
  1039.   rndr->fillRects(&drawrect);
  1040.  
  1041.   rndr->setDrawColor(GRAY(C0));
  1042.  
  1043.   rndr->drawRects(&drawrect);
  1044.  
  1045.   drawrect.x = drawrect.y = 0;
  1046.   rndr->drawRects(&drawrect);
  1047.  
  1048.   drawrect.y += 31;
  1049.   rndr->drawRects(&drawrect);
  1050.  
  1051.   drawrect.y = LOGI_H-32;
  1052.   rndr->drawRects(&drawrect);
  1053.  
  1054.   rndr->drawLine(31, 0, 31, LOGI_H-1);
  1055.   rndr->drawLine(RIGHT_EDGE, 0, RIGHT_EDGE, LOGI_H-1);
  1056.  
  1057.  
  1058.  
  1059.   rndr->setDrawColor(GRAY(FF));
  1060.  
  1061.   f32 percent = ((f32)settings.selected/(FILENAMES_LEN-1));
  1062.   s32 y = 63 + percent*(LOGI_H-3*32);
  1063.   rndr->drawLine(0, y, 30, y);
  1064.  
  1065.  
  1066.  
  1067.   BlendModesEnum mode = rndr->getDrawBlendMode();
  1068.   rndr->setDrawBlendMode(BLENDMODE_BLEND);
  1069.   rndr->setDrawColor(0x80FFFFFF);
  1070.  
  1071.   drawrect.x = 32;
  1072.   drawrect.y = 0;
  1073.   drawrect.w = RIGHT_EDGE-32;
  1074.   drawrect.h = TEXT_BASE_Y;
  1075.   rndr->fillRects(&drawrect);
  1076.   drawrect.y = TEXT_BASE_Y+8*TEXT_SCALE;
  1077.   rndr->fillRects(&drawrect);
  1078.  
  1079.   rndr->setDrawBlendMode(mode);
  1080.  
  1081.  
  1082.  
  1083.   text->scale = {TEXT_SCALE, TEXT_SCALE};
  1084.  
  1085.   u32 first = 0;
  1086.   u32 last  = MIN((u32)settings.selected+MAX_NAMES, FILENAMES_LEN-1);
  1087.  
  1088.   ctx.names->draw(32, TEXT_BASE_Y - settings.selected*8*TEXT_SCALE,
  1089.                   MAX_LEN, first, last);
  1090.  
  1091.  
  1092.  
  1093.   static f32 hue_value = 0.0f;
  1094.   shape::rect dst;
  1095.  
  1096.   dst = mouse_zones[MZONE_BACK];
  1097.   if(ctx.hover[MZONE_BACK]) draw_icon_hsv(dst.x, dst.y, 2,  hue_value);
  1098.   else                      draw_icon_rgb(dst.x, dst.y, 2, 0xFFFFFFFF);
  1099.  
  1100.   dst = mouse_zones[MZONE_UP];
  1101.   if(ctx.hover[MZONE_UP]) draw_icon_hsv(dst.x, dst.y, 4,  hue_value);
  1102.   else                    draw_icon_rgb(dst.x, dst.y, 4, 0xFFFFFFFF);
  1103.  
  1104.   dst = mouse_zones[MZONE_DOWN];
  1105.   if(ctx.hover[MZONE_DOWN]) draw_icon_hsv(dst.x, dst.y, 5,  hue_value);
  1106.   else                      draw_icon_rgb(dst.x, dst.y, 5, 0xFFFFFFFF);
  1107.  
  1108.   dst = mouse_zones[MZONE_PLAY];
  1109.   if(ctx.hover[MZONE_PLAY]) draw_icon_hsv(dst.x, dst.y, 6,  hue_value);
  1110.   else                      draw_icon_rgb(dst.x, dst.y, 6, 0xFFFFFFFF);
  1111.  
  1112.   hue_value += 2.0f;
  1113.  
  1114.  
  1115.  
  1116.   #if defined(_DEBUG) && 0
  1117.     rndr->setDrawColor(0xFFFF00FF);
  1118.     //if(!(frame_num%2))
  1119.       rndr->drawRects(mouse_zones, MOUSE_ZONES_LEN);
  1120.   #endif /* _DEBUG */
  1121.  
  1122. }
  1123.  
  1124.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement