Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /******************************************************************************/
- /******************************************************************************/
- //"sokoban_and_kit32_2025-01-31\kit32\simulator\src\kit_32_cpu_syscall.cpp":
- #include <include_all.hpp>
- #include <cmath> //for sqrtf, fmodf, and trig functions
- kit::Mutex* ewatch_lock = nullptr;
- namespace kit {
- #define EWATCH_LOCK(_bool) if(ewatch_lock){ ewatch_lock->lock(_bool); }
- static key32 key_queue[256];
- static u8 key_read_index = 0;
- static u8 key_write_index = 0;
- static key32 key_queue_read(){
- key32 key; //defaults to 0 (aka no event in queue)
- EWATCH_LOCK(true);
- if(key_read_index != key_write_index){
- key = key_queue[key_read_index++];
- }
- EWATCH_LOCK(false);
- return key;
- }
- static void key_queue_write(key32 key){
- EWATCH_LOCK(true);
- key_queue[key_write_index++] = key;
- //advance read index if last element was just overwritten
- if(key_read_index == key_write_index)
- ++key_read_index;
- EWATCH_LOCK(false);
- }
- #define r0 regs[0]
- #define r1 regs[1]
- #define r2 regs[2]
- #define r3 regs[3]
- #define r4 regs[4]
- #define r5 regs[5]
- #define sp regs_sp
- #define flg regs_flags
- #define pc regs_pc
- void cpu32::syscall(u16 type){
- switch(type){
- case SYSCALL_TAN : { r0.f32 = tanf(r0.f32); } break;
- case SYSCALL_COSSIN : { r1.f32 = sinf(r1.f32); } ATTR_FALLTHROUGH;
- case SYSCALL_COS : { r0.f32 = cosf(r0.f32); } break;
- case SYSCALL_SIN : { r1.f32 = sinf(r1.f32); } break;
- case SYSCALL_MEMSET : { memory::set( ADDR(u8,r0.u32), r1.u8, r2.u32); } break;
- case SYSCALL_MEMCPY : { memory::copy(ADDR(u8,r0.u32), ADDR(u8,r1.u32), r2.u32); } break;
- case SYSCALL_SETDRAWCOLOR : { rndr->setDrawColor(r0.u32); } break;
- case SYSCALL_DRAWPOINT_S32 : { rndr->drawPoint(r0.s32, r1.s32); } break;
- case SYSCALL_DRAWPOINT_F32 : { rndr->drawPoint(r0.f32, r1.f32); } break;
- case SYSCALL_DRAWLINE_S32 : { rndr->drawLine(r0.s32, r1.s32, r2.s32, r3.s32); } break;
- case SYSCALL_DRAWLINE_F32 : { rndr->drawLine(r0.f32, r1.f32, r2.f32, r3.f32); } break;
- case SYSCALL_DRAWRECT_S32 : { rndr->drawRects((shape::rect *)regs, 1); } break;
- case SYSCALL_DRAWRECT_F32 : { rndr->drawRects((shape::frect*)regs, 1); } break;
- case SYSCALL_FILLRECT_S32 : { rndr->fillRects((shape::rect *)regs, 1); } break;
- case SYSCALL_FILLRECT_F32 : { rndr->fillRects((shape::frect*)regs, 1); } break;
- #define drawXs(_call, _shp) \
- rndr->_call(ADDR(shape::_shp, r0.u32), r1.u32&KIT_S32_MAX)
- case SYSCALL_DRAWPOINTS_S32: { drawXs(drawPoints, point); } break;
- case SYSCALL_DRAWPOINTS_F32: { drawXs(drawPoints,fpoint); } break;
- case SYSCALL_DRAWLINES_S32 : { drawXs(drawLines , point); } break;
- case SYSCALL_DRAWLINES_F32 : { drawXs(drawLines ,fpoint); } break;
- case SYSCALL_DRAWRECTS_S32 : { drawXs(drawRects , rect ); } break;
- case SYSCALL_DRAWRECTS_F32 : { drawXs(drawRects ,frect ); } break;
- case SYSCALL_FILLRECTS_S32 : { drawXs(fillRects , rect ); } break;
- case SYSCALL_FILLRECTS_F32 : { drawXs(fillRects ,frect ); } break;
- case SYSCALL_CLEAR : { rndr->clear(); } break;
- case SYSCALL_PRESENT : {
- rndr->present();
- u64 ticksEnd = time::getTicks();
- s64 ticksDelta = ticksEnd-ticksStart;
- f64 timeDelta = (f64)ticksDelta/time::getTicksPerSecond();
- s32 timeDeltaMS = (s32)(timeDelta*1000.0f);
- u32 timeToSleepMS = MAX(16-timeDeltaMS, 1);
- time::sleep(timeToSleepMS);
- ticksStart = time::getTicks();
- } break;
- case SYSCALL_RAND_U8 : { r0.u8 = (u8 )(frandf_b()*KIT_U8_MAX ); } break;
- case SYSCALL_RAND_U16 : { r0.u16 = (u16)(frandf_b()*KIT_U16_MAX); } break;
- case SYSCALL_RAND_U32 : { r0.u32 = (u32)(frandf() *KIT_U32_MAX); } break;
- case SYSCALL_RAND_F32 : { r0.f32 = frandf(); } break;
- case SYSCALL_GETKEY : { r0.u32 = key_queue_read().value; } break;
- case SYSCALL_DRAWTEXT : {
- text->draw(r0.s32, r1.s32, ADDR(char,r2.u32), r3.u32&KIT_S32_MAX);
- } break;
- default:;
- }
- }
- }; /* namespace kit */
- using namespace kit;
- void ewatch_func(Event& evt, void* userdata){
- if(KIT_EVENT_ID(evt.type) != KEVENT_KEY) return;
- key32 key = convert_key(evt.key);
- key_queue_write(key);
- (void)userdata;
- }
- /******************************************************************************/
- /******************************************************************************/
- //"sokoban_and_kit32_2025-01-31\kit32\simulator\src\main.cpp":
- #include <include_all.hpp>
- #include <unistd.h> //for getcwd()
- #include <cstdlib> //for std::srand & std::rand
- #if RAND_MAX > 32767
- #error "RAND_MAX > 32767; frand should be altered to accomodate"
- #endif
- using namespace kit;
- /******************************************************************************/
- Window* wndw = nullptr;
- Renderer* rndr = nullptr;
- BFont_Texture* text = nullptr;
- BFont_Texture* textColored[16] = {0};
- /****************************** "callbacks.cpp" *******************************/
- s32 cb_audio(void* _dst, const AudioDeviceInfo& info);
- extern AudioDevice* audio;
- extern bool audioIsReady;
- /******************************************************************************/
- //assumes RAND_MAX is 32767
- #define GET_FRAND_VALUE(cast) ( (cast)(std::rand()<<15|std::rand())/0x3FFFFFFF )
- f64 frand (){ return GET_FRAND_VALUE(f64); } // 0.0f -> 1.0f
- f64 frand2 (){ return GET_FRAND_VALUE(f64)*2.0f - 1.0f; } //-1.0f -> 1.0f
- f32 frandf (){ return GET_FRAND_VALUE(f32); } // 0.0f -> 1.0f
- f32 frandf2(){ return GET_FRAND_VALUE(f32)*2.0f - 1.0f; } //-1.0f -> 1.0f
- f32 frandf_b (){ return (f32)std::rand()/RAND_MAX; }
- f32 frandf2_b(){ return ((f32)std::rand()/RAND_MAX)*2.0f - 1.0f; }
- /******************************************************************************/
- #define PREVENT_RUNNING_WHILE_ZIPPED 1
- int user_main(int argc, char** argv);
- int main(int argc, char** argv){ int returnStatus = -1; try {
- u64 timeDelta, timeStartAudio, timeStartAll = time::getMS();
- #if PREVENT_RUNNING_WHILE_ZIPPED == 1
- if(!(argc >= 2 && argv[1][0] == '/')){
- //this should hopefully prevent people from executing the program
- //before it's unzipped (in most cases, at least)
- #define EXTRACT_MSG "This program must be ran normally, after being unzipped"
- char cwd[256];
- getcwd(cwd, sizeof(cwd));
- cwd[255] = 0; //just in case
- u32 lastChar = strnLen(cwd)-1;
- if(cwd[lastChar]=='/' || cwd[lastChar]=='\\') cwd[lastChar] = 0;
- //first check
- //checks if the program's current working directory is
- //"C:\Users\<name>\AppData" (specific to windows)
- #if defined(_WIN32)
- {
- u32 i = 0, backSlashCount = 0;
- bool foundUsers = false;
- if((cwd[0]|32) == 'c') //(x|32 makes the char x lowercase)
- for(; i<256; ++i){ _start:
- if(cwd[i] == '\0') break;
- if(cwd[i] == '\\') ++backSlashCount;
- if(backSlashCount == 1){
- if(!strnCmp("Users", &cwd[++i], 5)) foundUsers = true;
- goto _start; //++i should only occur once this iteration
- }
- if(foundUsers && backSlashCount == 3){
- if(!strnCmp("AppData", &cwd[++i], 7)) throw EXTRACT_MSG;
- break;
- }
- }
- }
- #endif /* defined(_WIN32) */
- //second check
- //all this does is it clips the executable name from the
- //full path (argv[0]) to compare it to the current working directory
- //(this should work even if argv[0] is something else,
- //since you're supposed to run this program normally anyway)
- if(argc > 0){
- char* path = argv[0];
- size_t path_len = strnLen(path);
- s32 i = path_len-1;
- bool fwdSlash = false;
- if(path_len < 256)
- for(; i>=0; --i){
- fwdSlash = path[i]=='/';
- if(fwdSlash || path[i] == '\\'){ path[i] = 0; break; }
- }
- if(i >= 0){
- //throw if the paths are different
- if(strnCmp(path, cwd)) throw EXTRACT_MSG;
- //put slash back in case user wants to reference argv[0] too
- path[i] = (fwdSlash) ? '/' : '\\';
- }
- }
- }
- #endif /* PREVENT_RUNNING_WHILE_ZIPPED == 1 */
- initSubsystems(KINIT_EVERYTHING);
- /********************************* AUDIO INIT *********************************/
- AudioDeviceInfo audio_info = audiofunc::getDefaultDevInfo();
- audio_info.sampleFormat = SMPFMT_F32;
- audio_info.numChannels = 2;
- audio_info.zeroBuffer = true;
- audio_info.callback = cb_audio;
- audio_info.userdata = nullptr;
- //actually, for some reason setting audio_info's sampleRate to be lower
- //than 15701 causes _audio.pause() to hang indefinitely (for me at least)
- //tbd: figure out why this happens
- audio_info.sampleRate = MAX(audio_info.sampleRate, 15701);
- AudioDevice _audio(nullptr, audio_info, false); audio = &_audio;
- _audio.play(); //begin fading in audio
- timeStartAudio = time::getMS();
- //...
- /********************************* VIDEO INIT *********************************/
- audioIsReady = true;
- { //<- closes at the end of video cleanup
- Window _wndw(WIN_TITLE, WIN_W, WIN_H, WIN_FLAGS|WINFLAG_HIDDEN); wndw=&_wndw;
- Renderer _rndr(_wndw); rndr = &_rndr;
- #define GRAY(_hexvalue) 0xFF##_hexvalue##_hexvalue##_hexvalue
- BFont_Texture _text(_rndr, nullptr, nullptr, GRAY(FF), 16384); text = &_text;
- const clrs::ABGR textColored_colors[TEXTCOLORED_LEN] = {
- 0xFF000000, //gray0 ( 0)
- 0xFF555555, //gray1 ( 85)
- 0xFFAAAAAA, //gray2 (170)
- 0xFFFFFFFF, //gray3 (255)
- 0xFF000080, //redLo
- 0xFF0000FF, //redHi
- 0xFF008000, //greenLo
- 0xFF00FF00, //greenHi
- 0xFF800000, //blueLo
- 0xFFFF0000, //blueHi
- 0xFF808000, //cyanLo
- 0xFFFFFF00, //cyanHi
- 0xFF800080, //magentaLo
- 0xFFFF00FF, //magentaHi
- 0xFF008080, //yellowLo
- 0xFF00FFFF, //yellowHi
- };
- for(u32 i=0; i<TEXTCOLORED_LEN; ++i){
- textColored[i] = new BFont_Texture(_rndr, nullptr, nullptr,
- textColored_colors[i], 1024);
- }
- //...
- /********************************* USER MAIN **********************************/
- timeDelta = time::getMS()-timeStartAll;
- kit_LogInfo("Initialized in %llums", timeDelta);
- //audio's actual fade DELAY is 90ms, whereas the fade in after that is 10ms.
- //so 95 should put the audio at about halfway through the fade in
- timeDelta = time::getMS()-timeStartAudio;
- time::sleep((u32)MAX((s64)(95-timeDelta), 1));
- //_wndw.setVisibility(true); //this is generally done by the user
- std::srand((u32)time::getTicks());
- returnStatus = user_main(argc, argv);
- _wndw.setVisibility(false);
- _audio.pause(); //begin fading out audio
- /******************************* VIDEO CLEANUP ********************************/
- {
- //...
- }
- for(u32 i=0; i<TEXTCOLORED_LEN; ++i) NULLDELETE(textColored[i],BFont_Texture);
- } //garbage collect video init stuff
- /******************************* AUDIO CLEANUP ********************************/
- //audio's actual fadeout is 10ms, so waiting ~12ms total should be enough
- while(_audio.isPlaying()) time::sleep(4);
- _audio.lock(); //just in case
- {
- //...
- }
- _audio.unlock();
- /************************** CATCH EXCEPTION OR EXIT ***************************/
- } catch(const char* errorText){
- #ifdef _DEBUG
- kit_LogError("FATAL EXCEPTION OCCURRED: \"%s\"\n", errorText);
- #else
- showMsgBox(errorText, "FATAL EXCEPTION OCCURRED!", MSGBOX_ERROR);
- #endif /* _DEBUG */
- //redundant, as quitSubsystems already does this when given KINIT_EVERYTHING
- //freeThreadErrors();
- }
- //can't error, and is also safe to call even if no subsystems are active!
- quitSubsystems(KINIT_EVERYTHING);
- //a nonzero value indicates a memory leak!
- if(memory::getNumAllocations())
- kit_LogWarn("# OF ALLOCATIONS = %llu", memory::getNumAllocations());
- return returnStatus;
- }
- /******************************************************************************/
- /******************************************************************************/
- //"sokoban_and_kit32_2025-01-31\kit32\simulator\src\user_main.cpp":
- #include <include_all.hpp>
- //begone, unused parameter warning
- #define UM_RETURN(_val) { (void)argc, (void)argv; return (_val); }
- using namespace kit;
- /*
- void ewatch_func(Event& evt, void* userdata){
- switch(evt.type){
- case KEVENT_KEY
- }
- }
- */
- cpu32 cpu;
- shape::point windowSize(WIN_W, WIN_H);
- bool handleEvents(){
- bool run = true;
- Event evt;
- while(pollEvent(&evt))
- switch(evt.type){
- case KEVENT_QUIT: run = false; break;
- /*
- case KEVENT_KEY_DOWN: {
- bool size_changed = false;
- if(evt.key.vkey == VKEY_F11){
- windowSize.x = MAX(windowSize.x-LOGI_W, LOGI_W);
- windowSize.y = MAX(windowSize.y-LOGI_H, LOGI_H);
- size_changed = true;
- } else if(evt.key.vkey == VKEY_F12 && !evt.key.repeat){
- windowSize += {LOGI_W, LOGI_H};
- size_changed = true;
- }
- if(size_changed) wndw->setSize(windowSize.x, windowSize.y);
- } break;
- */
- default:;
- }
- return run;
- }
- char msgbox_buffer[512];
- void cpu_msgbox(){
- snPrintf(msgbox_buffer, sizeof(msgbox_buffer),
- "\
- r0=%f, r1=%f, r2=%f, r3=%f, r4=%f, r5=%f\n\n\
- r0=0x%08X, r1=0x%08X, r2=0x%08X, r3=0x%08X, r4=0x%08X, r5=0x%08X\n\n\
- sp=0x%08X, flg=0b%08X, pc=0x%08X\
- ",
- cpu.regs[0].f32, cpu.regs[1].f32, cpu.regs[2].f32, cpu.regs[3].f32, cpu.regs[4].f32, cpu.regs[5].f32,
- cpu.regs[0].u32, cpu.regs[1].u32, cpu.regs[2].u32, cpu.regs[3].u32, cpu.regs[4].u32, cpu.regs[5].u32,
- cpu.regs_sp.u32, bin_hex(cpu.regs_flags.u8), cpu.regs_pc
- );
- showMsgBox(msgbox_buffer, "cpu state:");
- }
- extern Mutex* ewatch_lock;
- void ewatch_func(Event& evt, void* userdata);
- int user_main(int argc, char** argv){
- BinaryData prgData("prg.bin");
- if(prgData.getSize() > MEMSIZEh)
- throw "input file size out of bounds";
- memory::WrapperSIMD memory(MEMSIZE+256);
- memory::set(memory.ptr, 0, MEMSIZE);
- memory::copy(memory.ptr, prgData.getData(), prgData.getSize());
- #define PERSISTENT_NAME "persistent_memory.bin"
- if(fileio::exists(PERSISTENT_NAME)){
- BinaryData persistentData(PERSISTENT_NAME);
- memory::copy(((u8*)memory.ptr)+MEMSIZEh,
- persistentData.getData(),
- MIN(persistentData.getSize(),MEMSIZEh));
- }
- cpu.memory = (u8*)memory.ptr;
- ewatch_lock = new Mutex;
- EventWatch ewatch(ewatch_func, ewatch_lock);
- rndr->setLogicalSize(LOGI_W, LOGI_H);
- wndw->setMinSize(LOGI_W, LOGI_H);
- wndw->setVisibility(true);
- while(true){
- if(!handleEvents()) break;
- if(cpu.execute() == EXERES_BRK) cpu_msgbox();
- }
- NULLDELETE(ewatch_lock, Mutex);
- wndw->setVisibility(false);
- fileio::writeAll(PERSISTENT_NAME, ((u8*)memory.ptr)+MEMSIZEh, MEMSIZEh);
- UM_RETURN(0);
- }
- /******************************************************************************/
- /******************************************************************************/
- //"sokoban_and_kit32_2025-01-31\kit32\simulator\src\utils_core.cpp":
- #include <include_all.hpp>
- using namespace kit;
- /******************************************************************************/
- /******************************************************************************/
- //"sokoban_and_kit32_2025-01-31\sokoban\src\callbacks.cpp":
- #include <include_all.hpp>
- using namespace kit;
- void cb_music_fade_in(void* userdata_a, void* userdata_b);
- void cb_music_fade_out(void* userdata_a, void* userdata_b);
- AudioDevice* audio = nullptr;
- bool audioIsReady = false;
- SoundEngine* sfx = nullptr;
- s32 music_index = -1;
- Xmp* music = nullptr;
- Stereo_s16* music_buffer_src = nullptr;
- Stereo_f32* music_buffer_dst = nullptr;
- AudioFade music_fade = {cb_music_fade_in, cb_music_fade_out};
- struct music_id_t { u32 name_index, pos = 0; }; //8B
- #define MUSIC_NAME_musicbox1 0
- #define MUSIC_NAME_PREFIX "dat/music/"
- static const char* music_names[] = {
- MUSIC_NAME_PREFIX "musicbox1_v2.xm",
- };
- #define MUSIC_IDS_LEN countof(music_ids, music_id_t)
- static music_id_t music_ids[] = {
- {MUSIC_NAME_musicbox1, 0}, //plays upon running the game
- {MUSIC_NAME_musicbox1, 2}, //plays after returning from a menu
- };
- bool music_playing = false;
- void cb_music_fade_in(void* userdata_a, void* userdata_b){
- u32 sampleRate = (u32)(u64)userdata_a; //lol
- (void)userdata_b;
- if(!sampleRate || !music || music_index < 0){
- music_fade.fadeIn = false;
- return;
- }
- if((u32)music_index >= MUSIC_IDS_LEN){ kit_LogError("music_index >= MUSIC_IDS_LEN"); return; }
- music_id_t id = music_ids[music_index];
- const char* name = music_names[id.name_index];
- if(name == nullptr){ kit_LogError("music name = nullptr"); return; }
- if(!fileio::exists(name)){ kit_LogError("music module \"%s\" doesn't exist", name); return; }
- s32 result = music->moduleLoad(name);
- if(result){ kit_LogError("failed to load music module \"%s\": code = %i", name, result); return; }
- result = music->playerStart(sampleRate);
- if(result){ kit_LogError("failed to start music player: code = %i", result); return; }
- music->setPlayerPosition(id.pos);
- music_playing = true;
- }
- void cb_music_fade_out(void* userdata_a, void* userdata_b){
- (void)userdata_a;
- (void)userdata_b;
- if(!music) return;
- music->moduleStop();
- music->moduleRelease();
- music->playerEnd();
- if(music_index >= 0) music_fade.fadeIn = true;
- music_playing = false;
- }
- #define src music_buffer_src
- #define dst music_buffer_dst
- static f32 music_vol_old = 0.0f;
- static s32 cb_music_thread(void* userdata){
- s32 result = 0;
- u32 dst_len = (u32)(u64)userdata; //lol
- u32 dst_size = dst_len*sizeof(Stereo_f32);
- u32 src_size = dst_len*sizeof(Stereo_s16);
- if(!music || !src || !dst){
- result = -KIT_XMP_ERROR_STATE; _err:
- if(dst) memory::set(dst, 0, dst_size);
- return result;
- }
- f32 t = 0.0f;
- const f32 t_inc = 1.0f/dst_len;
- if(music_playing){
- result = music->playBuffer(src, src_size, true);
- if(result) goto _err;
- //no need to multiply at all
- if(music_vol_old==1.0f && settings.music_vol==1.0f){
- for(u32 i=0; i<dst_len; ++i){
- dst[i].l = ((f32)src[i].l/32768);
- dst[i].r = ((f32)src[i].r/32768);
- }
- //no need to interpolate
- } else if(music_vol_old == settings.music_vol){
- for(u32 i=0; i<dst_len; ++i){
- dst[i].l = ((f32)src[i].l/32768) * settings.music_vol;
- dst[i].r = ((f32)src[i].r/32768) * settings.music_vol;
- }
- //must interpolate between old and new
- } else {
- for(u32 i=0; i<dst_len; ++i){
- f32 volume = LERP2(music_vol_old, settings.music_vol, t);
- dst[i].l = ((f32)src[i].l/32768) * volume;
- dst[i].r = ((f32)src[i].r/32768) * volume;
- t += t_inc;
- }
- }
- music_vol_old = settings.music_vol;
- } else { //no music is playing; set music buffer to 0
- memory::set(dst, 0, dst_size);
- }
- if(music_index < 0) music_fade.fadeIn = false;
- music_fade.applyFade(&dst->l, dst_len*2, 2);
- return result;
- }
- #undef src
- #undef dst
- s32 cb_audio(void* _dst, const AudioDeviceInfo& info){
- //music_buffer_src is the first thing to be freed in the 'audio cleanup'
- //portion of main(), so if it == nullptr, that means audio is in
- //the middle of being uninitialized
- //(that, or music_buffer_src simply hasn't been set yet,
- // in which case it should exit early anyway)
- if(!audioIsReady || music_buffer_src == nullptr) return 0;
- Stereo_f32* dst = (Stereo_f32*)_dst;
- u16 dst_len = info.sampleFrames;
- //process music in a separate thread...
- Thread music_thread(cb_music_thread, (void*)(u64)dst_len, true, 0, "music");
- //mix whatever sound effects that may be actively playing
- if(sfx) sfx->mixTracks(dst, dst_len, info.timeStartMS);
- s32 result = music_thread.waitUntilDone();
- if(result && result != -999) kit_LogError("music thread returned %i", result);
- for(u16 i=0; i<dst_len; ++i){
- //...before mixing its output into dst
- //(+= instead of =, since sfx has already mixed its own output into dst)
- dst[i].l += music_buffer_dst[i].l;
- dst[i].r += music_buffer_dst[i].r;
- //finally, clamp the samples so that they aren't out of bounds
- dst[i].l = CLAMP(dst[i].l, -1.0f, 1.0f);
- dst[i].r = CLAMP(dst[i].r, -1.0f, 1.0f);
- }
- return 0;
- }
- /******************************************************************************/
- /******************************************************************************/
- //"sokoban_and_kit32_2025-01-31\sokoban\src\ctx_lvl_editor.cpp":
- #include <include_all.hpp>
- using namespace kit;
- static struct {
- bool init = false;
- } ctx;
- static inline void reset_ctx(){
- if(ctx.init) return;
- memory::set(&ctx, 0, sizeof(ctx));
- cursor_scroll = true;
- cursor_snow = false;
- }
- s32 ctx_lvl_editor_evt(){
- reset_ctx();
- Event evt; bool run = true;
- return 0;
- }
- void ctx_lvl_editor_draw(){
- }
- /******************************************************************************/
- /******************************************************************************/
- //"sokoban_and_kit32_2025-01-31\sokoban\src\ctx_lvl_select.cpp":
- #include <include_all.hpp>
- using namespace kit;
- enum mouse_zone_names {
- MZONE_SLIDER,
- MZONE_BACK,
- MZONE_UP,
- MZONE_DOWN,
- MZONE_PLAY,
- MZONE_COUNT,
- };
- #define LEVELS_PATH "."
- #define UV_STEP(_amount) ((1.0f/ICON_MENU_LEN)*(_amount))
- #define FILENAME(_n) ctx.names->files[_n]
- #define FILENAME_C(_n) FILENAME(_n)->c_str()
- #define FILENAMES_LEN ctx.names->files_len
- #define TEXT_SCALE (1)
- #define MAX_LEN ( (LOGI_W-LOGI_H-32)/(8*TEXT_SCALE) )
- #define MAX_NAMES ( (LOGI_H/(8*TEXT_SCALE)) )
- static struct {
- file_list* names = nullptr;
- s32 opt = -1;
- bool hover[MZONE_COUNT];
- bool init = false;
- } ctx;
- #define destroy_filenames() NULLDELETE(ctx.names, file_list)
- static bool query_level_directory(){
- destroy_filenames();
- ctx.names = new file_list(LEVELS_PATH);
- return FILENAMES_LEN != 0;
- }
- #define SELECT(_newstate) \
- settings.selected = CLAMP((_newstate), 0, (s32)FILENAMES_LEN-1)
- #define SELECT_REL(_diff) \
- SELECT(settings.selected+(_diff))
- static inline void reset_ctx(){
- if(ctx.init) return;
- music_play(-1);
- destroy_filenames(); //just in case
- memory::set(&ctx, 0, sizeof(ctx));
- query_level_directory();
- ctx.opt = -1;
- settings.selected = CLAMP(settings.selected,
- 0, FILENAMES_LEN-1);
- ctx.init = true;
- cursor_scroll = false;
- cursor_snow = false;
- clear_snowflakes();
- }
- #define MOUSE_ZONES_LEN countof(mouse_zones, shape::rect)
- static shape::rect mouse_zones[] = {
- { 0, 63, 32, LOGI_H+1-3*32}, //slider
- { 0, 0, 32, 31}, //back
- { 0, 31, 32, 32}, //up
- { 0, LOGI_H-32, 32, 32}, //down
- {LOGI_W-32, LOGI_H-32, 32, 32}, //play
- };
- s32 ctx_lvl_select_evt(){
- reset_ctx();
- Event evt; bool run = true;
- #define WAS_MOUSE_DOWN (mouseClick && !mouseDrag)
- #define OPT_CHANGED (ctx.opt != opt_old && ctx.opt != -1)
- bool mouseDrag = true;
- bool mouseClick = false;
- s32 opt_old = ctx.opt;
- u32 ctx_which_old = ctx_which;
- if(ctx.names->files_len == 0){
- while(pollEvent(&evt) && run){
- if(evt.type == KEVENT_KEY_DOWN ||
- evt.type == KEVENT_MOUSE_DOWN)
- {
- ctx_which = CTX_MAIN_MENU;
- music_play(-2);
- }
- run = default_event_handler(evt);
- }
- } else while(pollEvent(&evt) && run)
- switch(evt.type){
- case KEVENT_MOUSE_DOWN: mouseDrag = false; ATTR_FALLTHROUGH;
- case KEVENT_MOUSE_MOVED: {
- mouseClick = evt.mouse.button!=0;
- ctx.opt = -1;
- for(u32 i=0; i<MOUSE_ZONES_LEN; ++i){
- shape::point pos = {evt.mouse.x, evt.mouse.y};
- if(point_in_rect(pos, mouse_zones[i])){
- if(opt_old != (s32)i){
- }
- ctx.opt = i; break;
- }
- }
- } goto _def_evt;
- case KEVENT_MOUSE_WHEEL: {
- SELECT_REL(-evt.mouse.dy);
- } goto _def_evt;
- default: _def_evt: run = default_event_handler(evt);
- }
- memory::set(ctx.hover, 0, sizeof(ctx.hover));
- if(ctx.opt >= 0) ctx.hover[ctx.opt] = true;
- if (ctx.opt>=MZONE_BACK && OPT_CHANGED ) SFXPLAY(SFXNAME_BLIP1, 1,1.2);
- else if(ctx.opt!=-1 && WAS_MOUSE_DOWN) SFXPLAY(SFXNAME_CHK1 , 1,1.0);
- switch(ctx.opt){
- case MZONE_UP : if(WAS_MOUSE_DOWN){ SELECT_REL(-1); } break;
- case MZONE_DOWN: if(WAS_MOUSE_DOWN){ SELECT_REL( 1); } break;
- case MZONE_BACK: if(WAS_MOUSE_DOWN){
- ctx_which = CTX_MAIN_MENU;
- music_play(-2);
- } break;
- case MZONE_PLAY: {
- //tbd
- } break;
- case MZONE_SLIDER: if(mouseClick){
- s32 adjusted = cursor_pos.y-mouse_zones[MZONE_SLIDER].y;
- f32 percent = (f32)adjusted/mouse_zones[MZONE_SLIDER].h;
- SELECT( (s32)(((FILENAMES_LEN-1)*percent)+0.5f) );
- } break;
- default:;
- }
- if(!run || ctx_which_old != ctx_which){
- destroy_filenames();
- ctx.init = false;
- return -run; //will return -1 unless run==0
- }
- return run;
- }
- #define RIGHT_EDGE (31+8*(TEXT_SCALE)*(MAX_LEN))
- #define TEXT_BASE_Y ( (LOGI_H/2 - (8*(TEXT_SCALE))/2) )
- void ctx_lvl_select_draw(){
- if(FILENAMES_LEN == 0){
- text->scale = {3,3};
- text->drawBox(KIT_CENTER_TEXT, KIT_CENTER_TEXT,
- "no levels found!");
- return;
- }
- rndr->setDrawColor(GRAY(00));
- shape::rect drawrect = {0,0, RIGHT_EDGE,LOGI_H};
- rndr->fillRects(&drawrect);
- drawrect = {LOGI_W-32, LOGI_H-32, 32, 32};
- rndr->fillRects(&drawrect);
- rndr->setDrawColor(GRAY(C0));
- rndr->drawRects(&drawrect);
- drawrect.x = drawrect.y = 0;
- rndr->drawRects(&drawrect);
- drawrect.y += 31;
- rndr->drawRects(&drawrect);
- drawrect.y = LOGI_H-32;
- rndr->drawRects(&drawrect);
- rndr->drawLine(31, 0, 31, LOGI_H-1);
- rndr->drawLine(RIGHT_EDGE, 0, RIGHT_EDGE, LOGI_H-1);
- rndr->setDrawColor(GRAY(FF));
- f32 percent = ((f32)settings.selected/(FILENAMES_LEN-1));
- s32 y = 63 + percent*(LOGI_H-3*32);
- rndr->drawLine(0, y, 30, y);
- BlendModesEnum mode = rndr->getDrawBlendMode();
- rndr->setDrawBlendMode(BLENDMODE_BLEND);
- rndr->setDrawColor(0x80FFFFFF);
- drawrect.x = 32;
- drawrect.y = 0;
- drawrect.w = RIGHT_EDGE-32;
- drawrect.h = TEXT_BASE_Y;
- rndr->fillRects(&drawrect);
- drawrect.y = TEXT_BASE_Y+8*TEXT_SCALE;
- rndr->fillRects(&drawrect);
- rndr->setDrawBlendMode(mode);
- text->scale = {TEXT_SCALE, TEXT_SCALE};
- u32 first = 0;
- u32 last = MIN((u32)settings.selected+MAX_NAMES, FILENAMES_LEN-1);
- ctx.names->draw(32, TEXT_BASE_Y - settings.selected*8*TEXT_SCALE,
- MAX_LEN, first, last);
- static f32 hue_value = 0.0f;
- shape::rect dst;
- dst = mouse_zones[MZONE_BACK];
- if(ctx.hover[MZONE_BACK]) draw_icon_hsv(dst.x, dst.y, 2, hue_value);
- else draw_icon_rgb(dst.x, dst.y, 2, 0xFFFFFFFF);
- dst = mouse_zones[MZONE_UP];
- if(ctx.hover[MZONE_UP]) draw_icon_hsv(dst.x, dst.y, 4, hue_value);
- else draw_icon_rgb(dst.x, dst.y, 4, 0xFFFFFFFF);
- dst = mouse_zones[MZONE_DOWN];
- if(ctx.hover[MZONE_DOWN]) draw_icon_hsv(dst.x, dst.y, 5, hue_value);
- else draw_icon_rgb(dst.x, dst.y, 5, 0xFFFFFFFF);
- dst = mouse_zones[MZONE_PLAY];
- if(ctx.hover[MZONE_PLAY]) draw_icon_hsv(dst.x, dst.y, 6, hue_value);
- else draw_icon_rgb(dst.x, dst.y, 6, 0xFFFFFFFF);
- hue_value += 2.0f;
- #if defined(_DEBUG) && 0
- rndr->setDrawColor(0xFFFF00FF);
- //if(!(frame_num%2))
- rndr->drawRects(mouse_zones, MOUSE_ZONES_LEN);
- #endif /* _DEBUG */
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement