From 8c9931cf5772e6b22a12e4eb8a2e444d31772eed Mon Sep 17 00:00:00 2001 From: chaoskagami Date: Fri, 22 Aug 2014 18:10:32 -0400 Subject: [PATCH] Initial commit --- build | 22 ++ external/include/zero/AudioManager.hpp | 36 ++ external/include/zero/ContextManager.hpp | 109 ++++++ external/include/zero/TextManager.hpp | 45 +++ external/include/zero/UDisplayable.hpp | 71 ++++ external/include/zero/Zero.hpp | 14 + external/src/zero/AudioManager.cpp | 167 +++++++++ external/src/zero/ContextManager.cpp | 453 +++++++++++++++++++++++ external/src/zero/TextManager.cpp | 130 +++++++ external/src/zero/UDisplayable.cpp | 362 ++++++++++++++++++ mk | 62 ++++ vndc/include/Data.hpp | 45 +++ vndc/include/Funcs.hpp | 38 ++ vndc/src/Data.cpp | 59 +++ vndc/src/Loop.cpp | 66 ++++ vndc/src/Parse.cpp | 268 ++++++++++++++ vndc/src/VNDC.cpp | 115 ++++++ vndc/src/op_bgload.cpp | 45 +++ vndc/src/op_choice.cpp | 100 +++++ vndc/src/op_cleartext.cpp | 52 +++ vndc/src/op_delay.cpp | 18 + vndc/src/op_fi.cpp | 12 + vndc/src/op_goto.cpp | 50 +++ vndc/src/op_gsetvar.cpp | 25 ++ vndc/src/op_if.cpp | 59 +++ vndc/src/op_jump.cpp | 47 +++ vndc/src/op_music.cpp | 30 ++ vndc/src/op_random.cpp | 21 ++ vndc/src/op_setimg.cpp | 30 ++ vndc/src/op_setvar.cpp | 37 ++ vndc/src/op_sound.cpp | 44 +++ vndc/src/op_text.cpp | 119 ++++++ 32 files changed, 2751 insertions(+) create mode 100755 build create mode 100644 external/include/zero/AudioManager.hpp create mode 100644 external/include/zero/ContextManager.hpp create mode 100644 external/include/zero/TextManager.hpp create mode 100644 external/include/zero/UDisplayable.hpp create mode 100644 external/include/zero/Zero.hpp create mode 100644 external/src/zero/AudioManager.cpp create mode 100644 external/src/zero/ContextManager.cpp create mode 100644 external/src/zero/TextManager.cpp create mode 100644 external/src/zero/UDisplayable.cpp create mode 100755 mk create mode 100644 vndc/include/Data.hpp create mode 100644 vndc/include/Funcs.hpp create mode 100644 vndc/src/Data.cpp create mode 100644 vndc/src/Loop.cpp create mode 100644 vndc/src/Parse.cpp create mode 100644 vndc/src/VNDC.cpp create mode 100644 vndc/src/op_bgload.cpp create mode 100644 vndc/src/op_choice.cpp create mode 100644 vndc/src/op_cleartext.cpp create mode 100644 vndc/src/op_delay.cpp create mode 100644 vndc/src/op_fi.cpp create mode 100644 vndc/src/op_goto.cpp create mode 100644 vndc/src/op_gsetvar.cpp create mode 100644 vndc/src/op_if.cpp create mode 100644 vndc/src/op_jump.cpp create mode 100644 vndc/src/op_music.cpp create mode 100644 vndc/src/op_random.cpp create mode 100644 vndc/src/op_setimg.cpp create mode 100644 vndc/src/op_setvar.cpp create mode 100644 vndc/src/op_sound.cpp create mode 100644 vndc/src/op_text.cpp diff --git a/build b/build new file mode 100755 index 0000000..aa6e260 --- /dev/null +++ b/build @@ -0,0 +1,22 @@ +#!/bin/bash + +ROOT=`pwd` +SRC=$ROOT/ +LIB=$ROOT/external/lib +BIN=$ROOT/bin + +source mk + +INCLUDE="-I$ROOT/external/include/zero -I$ROOT/vndc/include" + +newtd + mkmcc external/src/zero + mkar libZero +deltd + +LDFLAGS=-lZero + +newtd + mkmcc vndc/src + mkld vndc +deltd diff --git a/external/include/zero/AudioManager.hpp b/external/include/zero/AudioManager.hpp new file mode 100644 index 0000000..fd22d39 --- /dev/null +++ b/external/include/zero/AudioManager.hpp @@ -0,0 +1,36 @@ +#ifndef AUDIOMANAGER_HPP +#define AUDIOMANAGER_HPP + + + class AudioManager { + public: + // Ctors and dtors + AudioManager(); + ~AudioManager(); + + // Load index. + int LoadSfx(char* fname); + int LoadMusic(char* fname); + + // Playing functions. + void PlaySfx(int index); + void PlaySfx(int index, int count); + void PlayMusic(int index); + void PlayMusicLoop(int index); + void PauseMusic(); + + // Unload Functions + void UnloadSfx(int index); + void UnloadMusic(int index); + + // Complete unload functions + void FlushSfx(); + void FlushMusic(); + private: + int SfxCount = 0, MusicCount = 0; + Mix_Chunk** SfxStore = NULL; + Mix_Music** MusicStore = NULL; + }; + + +#endif diff --git a/external/include/zero/ContextManager.hpp b/external/include/zero/ContextManager.hpp new file mode 100644 index 0000000..6d1f976 --- /dev/null +++ b/external/include/zero/ContextManager.hpp @@ -0,0 +1,109 @@ +#ifndef CONTEXTMANAGER_HPP +#define CONTEXTMANAGER_HPP + +typedef void (*GameCallback)(bool); +typedef void (*MouseCallback)(int, int, bool, bool, bool, bool); // X, Y, up/down, isLeft, isMiddle, isRight + +class TextManager; // Forward decl + + // Input Mode enum. This is the max events allowed in one go. + typedef enum InMode_e { + Slow = 20, + Medium = 10, + Burst = 5 + } InMode; + + class ContextManager { + public: + ContextManager(); + ContextManager(int scr_width, int scr_height, bool fulls, bool accel); + + // Initialization. + void InitWindow(int width, int height, bool fulls, bool accel); + void InitWindowLogical(int width, int height, int width_log, int height_log, bool fulls, bool accel); + + // Set window title + void SetTitle(char* title); + + // Display related. + void Clear(); + void Flush(); + + void ClearOverlay(); + + SDL_Surface* Surface(); + SDL_Renderer* Renderer(); + bool Accelerated(); + void Blit(void* inp, SDL_Rect* src, SDL_Rect* dst); + void OverlayBlit(void* inp, SDL_Rect* src, SDL_Rect* dst); + + // Support funcs. + int GetWidth(); + int GetHeight(); + + // Get Input State and Modify input state. + bool Input(); + + // Abstract remappable key functions. + int RegisterInput(SDL_Keycode key, GameCallback func); + void RegisterMouse(MouseCallback func); + bool GetInput(int index); + void RemapKey(int index, SDL_Keycode to); + void InputMode(InMode mode); + + // Gets the AudioManager & TextManager + AudioManager* Audio(); + TextManager* Text(); + + // Exit methods. + void SetQuit(); + bool GetQuit(); + + // Logic sync limiter. + void StartSync(); + void EndSync(); + + ~ContextManager(); + private: + // Lower init. + // DELETEME - Software rendering doesn't work now. + void _InitWindowSW(int width, int height, bool fulls); + void _InitWindowAC(int width, int height, bool fulls); + // DELETEME - Software rendering doesn't work now. + void _InitWindowLogicalSW(int width_win, int height_win, int width_log, int height_log, bool fulls); + void _InitWindowLogicalAC(int width_win, int height_win, int width_log, int height_log, bool fulls); + + InMode inputmode = Medium; + SDL_Window* window = NULL; + SDL_Surface* surface = NULL, *surface_o = NULL; + SDL_Texture* texture = NULL, *texture_o = NULL; + SDL_Renderer* renderer = NULL; + // use logical size + bool logicalRender = false; + bool accelerate = false; + + bool StartQuit = false; + + AudioManager* audioMgr = NULL; + TextManager* txtMgr = NULL; + + SDL_Keycode* inputMappings = NULL; // This can actually be used instead of InputList now. Weird. + bool* inputStates = NULL; + GameCallback* inputCallbacks = NULL; + MouseCallback mouseCallback = NULL; + + int inputRegistered = 0; + + // Logic cap. + int logicRate = 60; + int timeElapsed = 0; + int syncElapsed = 0; + + // Width and height + int WIN_width = 0; + int WIN_height = 0; + int LOG_width = 0; + int LOG_height = 0; + }; + +#endif diff --git a/external/include/zero/TextManager.hpp b/external/include/zero/TextManager.hpp new file mode 100644 index 0000000..7e97530 --- /dev/null +++ b/external/include/zero/TextManager.hpp @@ -0,0 +1,45 @@ + +class TextManager { + public: + // Ctors & Dtors + TextManager(ContextManager* ct); + ~TextManager(); + + // Base font functions. + int LoadFont(char* fname); + void Render(char* text); + void Render(char* text, int x, int y); + + int TestLen(char* text); + void Outline(int pixels); + + // Property functions. + // void SetStyle(int style); + // void SetFontUsed(int font); + void SetColor(int r, int g, int b, int a); + + // Complex functions. + // Like printf but with formatting codes. Also not varargs. + // Should support this subset of standards: + // %d %u %x %c %s %f %% + // It also should have the following: + // %t - Font Index. Switches to font index. + // %p - Style. Sets style to S. + // %m - Expects an SDL_Color. Sets the color. + // void fnoutf(char* text, void** data); + + // Uses control codes, unline fnoutf. Mainly intended for scripts. + // These ops should be implemented: + // ^b (bold) ^i (italic) ^r (normal / reset) ^fI (font -> i) + // ^cNNN (color -> #NNN) ^n (next line) ^c (clear) + // void scoutf(char* text); + + private: + TTF_Font** fonts = NULL; + int current_font = 0; + int fonts_loaded = 0; + SDL_Color color; + ContextManager* ctx = NULL; + bool outline = false; + int outline_px = 0; +}; diff --git a/external/include/zero/UDisplayable.hpp b/external/include/zero/UDisplayable.hpp new file mode 100644 index 0000000..076bdd8 --- /dev/null +++ b/external/include/zero/UDisplayable.hpp @@ -0,0 +1,71 @@ +#ifndef UDISPLAYABLE_HPP +#define UDISPLAYABLE_HPP + +typedef enum { + Normal=1, + Hitbox=2, + Docked=3, + HitboxDocked=4, + Anim=5, // nyi + AnimHitbox=6, // nyi + AnimDocked=7, // nyi + AnimHitboxDocked=8 // nyi +} UDisplayableMode; + + class UDisplayable { + public: + UDisplayable(ContextManager* ctx, char* fname); // Sets up in normal mode. + UDisplayable(ContextManager* ctx, UDisplayableMode mode, char* fname); // Sets up in specified mode; params not set + UDisplayable(ContextManager* ctx, UDisplayableMode mode, void* memory, int mSize); // Sets up from memory block in mode + + // All modes can use the following. + void SetXY(double x, double y); + void ModXY(double xd, double yd); + + double GetX(); + double GetY(); + + int GetXI(); + int GetYI(); + + void Blit(); + + int* GetHitbox(); + + ~UDisplayable(); + + // Only specific modes can use these. Otherwise, they nop. + void SetHitbox(int x, int y, int w, int h); + void SetDock(int x, int y, int w, int h); + + // Only animated Displayables can use these. + void SetFrameWidth(int frameW); + void NextFrame(); + void NextFrame(int f); + void ResetFrame(); + void SetFrame(int f); + + + protected: + double x, y; + void* bitmap = NULL; // Will contain either a SDL_Surface or SDL_Texture + SDL_Rect loc, clip; + ContextManager* ctx; + + int bmp_w = 0, bmp_h = 0; + + // Used in docked mode + int* frame = NULL; + // Used in hitbox mode + int* hitbox = NULL; + + // The current mode. + UDisplayableMode dispMode = Normal; + + // Used by animated mode. + int frameIndex = -1; + int frameWidth; + + bool Error = false; + }; +#endif diff --git a/external/include/zero/Zero.hpp b/external/include/zero/Zero.hpp new file mode 100644 index 0000000..cfbdffe --- /dev/null +++ b/external/include/zero/Zero.hpp @@ -0,0 +1,14 @@ +#ifndef _ZERO_LIBRARY_HPP +#define _ZERO_LIBRARY_HPP + +#include +#include +#include +#include + +#include "AudioManager.hpp" +#include "ContextManager.hpp" +#include "TextManager.hpp" +#include "UDisplayable.hpp" + +#endif diff --git a/external/src/zero/AudioManager.cpp b/external/src/zero/AudioManager.cpp new file mode 100644 index 0000000..c3cadc8 --- /dev/null +++ b/external/src/zero/AudioManager.cpp @@ -0,0 +1,167 @@ +#include "Zero.hpp" + + // Sets up. + AudioManager::AudioManager() { + int MixerFlags = MIX_INIT_OGG | MIX_INIT_FLAC | MIX_INIT_MP3; + if((Mix_Init(MixerFlags) & MixerFlags) != MixerFlags) { + // Failed to load. + fprintf(stderr, "[E] Failed on Mix_Init. Reported error:\n"); + fprintf(stderr, "[E] %s\n", Mix_GetError()); + fprintf(stderr, "[E] Fatal. Dying.\n"); + exit(-1); + } + + uint16_t fmt = 0; + int freq = 0, chan = 0; + Mix_QuerySpec(&freq, &fmt, &chan); + + if (Mix_OpenAudio(freq, fmt, chan, 1024)) { + printf("[Mix:err] %s\n", Mix_GetError()); + exit(-7); + } + + Mix_AllocateChannels(64); // 32 Sfx + 1 Music + } + + // Cleans up everything. + AudioManager::~AudioManager() { + Mix_HaltChannel(-1); + Mix_HaltMusic(); + + while (SfxCount > 0) { + Mix_FreeChunk(SfxStore[SfxCount-1]); + --SfxCount; + } + + while (MusicCount > 0) { + Mix_FreeMusic(MusicStore[MusicCount-1]); + --MusicCount; + } + + free(SfxStore); + free(MusicStore); + + Mix_CloseAudio(); + + while(Mix_Init(0)) + Mix_Quit(); + } + + int AudioManager::LoadSfx(char* fname) { + ++SfxCount; + SfxStore = (Mix_Chunk**)realloc(SfxStore, sizeof(Mix_Chunk*) * SfxCount); + + memset(&SfxStore[SfxCount-1], 0, sizeof(Mix_Chunk*)); + + SfxStore[SfxCount-1] = NULL; + + SfxStore[SfxCount-1] = Mix_LoadWAV(fname); + + if(!SfxStore[SfxCount-1]) { + --SfxCount; + SfxStore = (Mix_Chunk**)realloc(SfxStore, sizeof(Mix_Chunk*) * SfxCount); + return -1; + } + + return SfxCount - 1; + } + + int AudioManager::LoadMusic(char* fname) { + ++MusicCount; + MusicStore = (Mix_Music**)realloc(MusicStore, sizeof(Mix_Music*) * MusicCount); + + memset(&MusicStore[MusicCount-1], 0, sizeof(Mix_Music*)); + + MusicStore[MusicCount-1] = NULL; + + MusicStore[MusicCount-1] = Mix_LoadMUS(fname); + + if(!MusicStore[MusicCount-1]) { + --MusicCount; + MusicStore = (Mix_Music**)realloc(MusicStore, sizeof(Mix_Music*) * MusicCount); + return -1; + } + + return MusicCount - 1; + } + + void AudioManager::PlaySfx(int index) { + if(index == -1) + return; + + if (index > SfxCount-1) + return; // Not a valid index. No-op. + + Mix_PlayChannel(-1, SfxStore[index], 0); + } + + void AudioManager::PlaySfx(int index, int count) { + if(index == -1) + return; + + if (index > SfxCount-1) + return; // Not a valid index. No-op. + + Mix_PlayChannel(-1, SfxStore[index], count); + } + + void AudioManager::PlayMusic(int index) { + if(index == -1) + return; + + // FIXME - Implement this. + Mix_PlayMusic(MusicStore[index], 0); + } + + void AudioManager::PlayMusicLoop(int index) { + if(index == -1) + return; + + // FIXME - Implement this. + Mix_PlayMusic(MusicStore[index], -1); + } + + void AudioManager::PauseMusic() { + // FIXME - Implement this. + Mix_PauseMusic(); + } + + void AudioManager::UnloadSfx(int index) { + if(index == -1) + return; + + Mix_FreeChunk(SfxStore[index]); + } + + void AudioManager::UnloadMusic(int index) { + if(index == -1) + return; + + Mix_FreeMusic(MusicStore[index]); + } + + // Unload all sfx + void AudioManager::FlushSfx() { + Mix_HaltChannel(-1); + + while (SfxCount > 0) { + Mix_FreeChunk(SfxStore[SfxCount-1]); + --SfxCount; + } + + free(SfxStore); + SfxStore = NULL; + } + + // Unload all music. + void AudioManager::FlushMusic() { + Mix_HaltMusic(); + + while (MusicCount > 0) { + Mix_FreeMusic(MusicStore[MusicCount-1]); + --MusicCount; + } + + free(MusicStore); + MusicStore = NULL; + } diff --git a/external/src/zero/ContextManager.cpp b/external/src/zero/ContextManager.cpp new file mode 100644 index 0000000..a645cab --- /dev/null +++ b/external/src/zero/ContextManager.cpp @@ -0,0 +1,453 @@ +#include "Zero.hpp" + + + // Initializes SDL and saves stuff into the context. + + ContextManager::ContextManager(int scr_width, int scr_height, bool fulls, bool accel) { + if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) < 0) { + #ifdef DEBUG_OVERKILL + printf("[ContextManager~Ctor] SDL Init error w/ VIDEO|AUDIO. Msg rep: %s\n", SDL_GetError()); + #else + printf("Error initializing SDL. Info:%s\n", SDL_GetError()); + #endif + } + else { + this->InitWindow(scr_width, scr_height, fulls, accel); + } + + audioMgr = new AudioManager(); + } + + // Delays window creation; Use InitWindow before doing anything. + + ContextManager::ContextManager() { + if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) < 0) { + #ifdef DEBUG_OVERKILL + printf("[ContextManager~Ctor] SDL Init error w/ VIDEO|AUDIO. Msg rep: %s\n", SDL_GetError()); + #else + printf("Error initializing SDL. Info:%s\n", SDL_GetError()); + #endif + } + + audioMgr = new AudioManager(); + } + + // Creates a window. + + void ContextManager::InitWindow(int width, int height, bool fulls, bool accel) { + this->WIN_width = width; + this->WIN_height = height; + this->LOG_width = width; + this->LOG_height = height; + + #ifdef DEBUG_OVERKILL + printf("[ContextManager::InitWindow] Params: w:%d h:%d f:%d a:%d\n", width, height, fulls, accel); + #endif + + if(accel) { + _InitWindowAC(width, height, fulls); + this->texture_o = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height); + SDL_SetTextureBlendMode(this->texture_o, SDL_BLENDMODE_BLEND); + } + else { + _InitWindowSW(width, height, fulls); + this->surface_o = SDL_CreateRGBSurface(0, width, height, 32, 0, 0, 0, 0); + } + + txtMgr = new TextManager(this); + } + + void ContextManager::_InitWindowSW(int width, int height, bool fulls) { + // Add title setting function. + this->window = SDL_CreateWindow("Zero", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN); + if(this->window == NULL) { + fprintf(stderr, "[E] Error creating window. Info:\n"); + fprintf(stderr, "[E] %s\n", SDL_GetError()); + fprintf(stderr, "[E] This is fatal. Dying."); + exit(-1); + } + else { + SDL_SetHintWithPriority(SDL_HINT_RENDER_VSYNC, "1", SDL_HINT_OVERRIDE); + if(!SDL_CreateRenderer( this->window, -1, SDL_RENDERER_ACCELERATED )) { + fprintf(stderr, "[E] Error creating renderer. Info:\n"); + fprintf(stderr, "[E] %s\n", SDL_GetError()); + fprintf(stderr, "[E] This is fatal. Dying."); + exit(-1); + } + } + } + + void ContextManager::_InitWindowAC(int width, int height, bool fulls) { + this->accelerate = true; + + this->window = SDL_CreateWindow("Zero", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN); + if(this->window == NULL) { + fprintf(stderr, "[E] Error creating window. Info:\n"); + fprintf(stderr, "[E] %s\n", SDL_GetError()); + fprintf(stderr, "[E] This is fatal. Dying."); + exit(-1); + } + else { + this->renderer = SDL_CreateRenderer( this->window, -1, SDL_RENDERER_ACCELERATED ); + if(this->renderer == NULL) { + fprintf(stderr, "[E] Error creating renderer. Info:\n"); + fprintf(stderr, "[E] %s\n", SDL_GetError()); + fprintf(stderr, "[E] This is fatal. Dying."); + exit(-1); + } + else { + this->logicalRender = true; + + this->texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height); + } + } + } + + // Init window with a logical size and a real one. Determines which backend to use. + void ContextManager::InitWindowLogical(int width_win, int height_win, int width_log, int height_log, bool fulls, bool accel) { + this->LOG_width = width_log; + this->LOG_height = height_log; + this->WIN_width = width_win; + this->WIN_height = height_win; + + #ifdef DEBUG_OVERKILL + printf("[ContextManager::InitWindowLogical] phyw:%d phyh:%d logw:%d logh:%d f:%d a:%d\n", width_win, height_win, width_log, height_log, fulls, accel); + #endif + + if (accel) { + _InitWindowLogicalAC(width_win, height_win, width_log, height_log, fulls); + this->texture_o = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width_win, height_win); + SDL_SetTextureBlendMode(this->texture_o, SDL_BLENDMODE_BLEND); + } + else { + _InitWindowLogicalSW(width_win, height_win, width_log, height_log, fulls); + this->surface_o = SDL_CreateRGBSurface(0, width_win, height_win, 32, 0, 0, 0, 0); + } + + txtMgr = new TextManager(this); + } + + // Init window with a logical size and a real one. + void ContextManager::_InitWindowLogicalSW(int width_win, int height_win, int width_log, int height_log, bool fulls) { + this->window = SDL_CreateWindow("Zero", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width_win, height_win, SDL_WINDOW_SHOWN); + if(this->window == NULL) { + fprintf(stderr, "[E] Error creating window. Info:\n"); + fprintf(stderr, "[E] %s\n", SDL_GetError()); + fprintf(stderr, "[E] This is fatal. Dying."); + exit(-1); + } + else { + this->renderer = SDL_CreateRenderer( this->window, -1, SDL_RENDERER_ACCELERATED ); + if(this->renderer == NULL) { + fprintf(stderr, "[E] Error creating renderer. Info:\n"); + fprintf(stderr, "[E] %s\n", SDL_GetError()); + fprintf(stderr, "[E] This is fatal. Dying."); + exit(-1); + } + else { + this->logicalRender = true; + + this->surface = SDL_CreateRGBSurface(0, width_log, height_log, 32, 0, 0, 0, 0); + } + } + } + + // Init window with a logical size and a real one. + void ContextManager::_InitWindowLogicalAC(int width_win, int height_win, int width_log, int height_log, bool fulls) { + this->accelerate = true; + + this->window = SDL_CreateWindow("Zero", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width_win, height_win, SDL_WINDOW_SHOWN); + if(this->window == NULL) { + fprintf(stderr, "[E] Error creating window. Info:\n"); + fprintf(stderr, "[E] %s\n", SDL_GetError()); + fprintf(stderr, "[E] This is fatal. Dying."); + exit(-1); + } + else { + this->renderer = SDL_CreateRenderer( this->window, -1, SDL_RENDERER_ACCELERATED ); + if(this->renderer == NULL) { + fprintf(stderr, "[E] Error creating renderer. Info:\n"); + fprintf(stderr, "[E] %s\n", SDL_GetError()); + fprintf(stderr, "[E] This is fatal. Dying."); + exit(-1); + } + else { + this->logicalRender = true; + + this->texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width_log, height_log); + } + } + } + + // Clears the display to black. + + void ContextManager::Clear() { + if(this->StartQuit) return; + + if (accelerate) { + if (logicalRender) { + SDL_SetRenderTarget(renderer, texture); + SDL_RenderClear(renderer); + SDL_SetRenderTarget(renderer, NULL); + } + + SDL_SetRenderTarget(renderer, texture_o); + SDL_RenderClear(renderer); + SDL_SetRenderTarget(renderer, NULL); + + SDL_RenderClear(renderer); + } + else { + if (logicalRender) + SDL_FillRect(this->surface, NULL, SDL_MapRGB(this->surface->format, 0x0, 0x0, 0x0)); + SDL_FillRect(this->surface_o, NULL, SDL_MapRGB(this->surface_o->format, 0x0, 0x0, 0x0)); + + SDL_FillRect(SDL_GetWindowSurface(this->window), NULL, SDL_MapRGB(SDL_GetWindowSurface(this->window)->format, 0x0, 0x0, 0x0)); + } + } + + // Clears the display to black. + + void ContextManager::ClearOverlay() { + if(this->StartQuit) return; + + if (accelerate) { + SDL_SetRenderTarget(renderer, texture_o); + SDL_RenderClear(renderer); + SDL_SetRenderTarget(renderer, NULL); + } + else { + SDL_FillRect(this->surface_o, NULL, SDL_MapRGB(this->surface_o->format, 0x0, 0x0, 0x0)); + } + } + + // Flush any changes in the surface to screen + + void ContextManager::Flush() { + if(this->StartQuit) return; + if (accelerate) { + if(logicalRender) { + SDL_Rect dst, src; + + src.x = 0; + src.y = 0; + src.w = LOG_width; + src.h = LOG_height; + + dst.x = 0; + dst.y = 0; + dst.w = WIN_width; + dst.h = WIN_height; + + SDL_RenderCopy(renderer, texture, &src, &dst); + } + + SDL_RenderCopy(renderer, texture_o, NULL, NULL); + + SDL_RenderPresent(renderer); + } + else { + if(logicalRender) + SDL_BlitScaled(this->surface, NULL, SDL_GetWindowSurface(this->window), NULL); + + SDL_BlitScaled(this->surface_o, NULL, SDL_GetWindowSurface(this->window), NULL); + + SDL_UpdateWindowSurface(this->window); + } + } + + // Return the internal surface for external blits. + SDL_Surface* ContextManager::Surface() { + if(this->StartQuit) return NULL; + if(accelerate) return NULL; + + if( logicalRender ) + return this->surface; + + return SDL_GetWindowSurface(this->window); + } + + // return the renderer. + SDL_Renderer* ContextManager::Renderer() { + return renderer; + } + + // return the renderer. + bool ContextManager::Accelerated() { + return accelerate; + } + + // Blit data via cast. inp should be a SDL_Surface or SDL_Texture. + void ContextManager::Blit(void* inp, SDL_Rect* src, SDL_Rect* dst) { + if(accelerate) { + if (logicalRender) SDL_SetRenderTarget(renderer, texture); + + SDL_RenderCopy(renderer, (SDL_Texture*)inp, src, dst); + + if (logicalRender) SDL_SetRenderTarget(renderer, NULL); + } + else { + SDL_BlitSurface((SDL_Surface*)inp, src, surface, dst); + } + } + + // Blit data to overlay via cast. inp should be a SDL_Surface or SDL_Texture. + void ContextManager::OverlayBlit(void* inp, SDL_Rect* src, SDL_Rect* dst) { + // Recalculate src and dst based on upscale. + double OUTW_Ratio, OUTH_Ratio; + OUTW_Ratio = (double)WIN_width / (double)LOG_width; + OUTH_Ratio = (double)WIN_height / (double)LOG_height; + + dst->x = (int)(((double)dst->x) * OUTW_Ratio); + dst->y = (int)(((double)dst->y) * OUTH_Ratio); + dst->w = (int)(((double)dst->w) * OUTW_Ratio); + dst->h = (int)(((double)dst->h) * OUTH_Ratio); + + if(accelerate) { + if (logicalRender) SDL_SetRenderTarget(renderer, texture_o); + + SDL_RenderCopy(renderer, (SDL_Texture*)inp, src, dst); + + if (logicalRender) SDL_SetRenderTarget(renderer, NULL); + } + else { + SDL_BlitSurface((SDL_Surface*)inp, src, surface_o, dst); + } + } + + // Gets width of display + int ContextManager::GetWidth() { + return this->LOG_width; + } + + // Gets height of display + int ContextManager::GetHeight() { + return this->LOG_height; + } + + // Checks input events for matches and run callbacks. + bool ContextManager::Input() { + if(this->StartQuit) return this->StartQuit; + + SDL_Event evt; + for(int i = 0; i < this->inputmode && SDL_PollEvent(&evt); i++) { + for(int j = 0; j < inputRegistered; j++) { + if(inputMappings[j] == evt.key.keysym.sym) { + bool down = false; + if(evt.type == SDL_KEYDOWN) + down = true; + inputStates[j] = down; + if((evt.type == SDL_KEYDOWN || evt.type == SDL_KEYUP) && inputCallbacks[j] != NULL) { + (inputCallbacks[j])(down); + } + } + } + if((evt.type == SDL_MOUSEBUTTONDOWN || evt.type == SDL_MOUSEBUTTONUP) && mouseCallback != NULL) { + if(evt.button.button == SDL_BUTTON_LEFT) { + (mouseCallback)(evt.button.x, evt.button.y, (evt.type == SDL_MOUSEBUTTONDOWN), true, false, false); + } + if(evt.button.button == SDL_BUTTON_MIDDLE) { + (mouseCallback)(evt.button.x, evt.button.y, (evt.type == SDL_MOUSEBUTTONDOWN), false, true, false); + } + if(evt.button.button == SDL_BUTTON_RIGHT) { + (mouseCallback)(evt.button.x, evt.button.y, (evt.type == SDL_MOUSEBUTTONDOWN), false, false, true); + } + } + } + + return this->StartQuit; + } + + // Changes the Input Mode used. + void ContextManager::InputMode(InMode in) { + inputmode = in; + } + + // Register an abstract handler. Returns an int corresponding to the index for the mapping. + int ContextManager::RegisterInput(SDL_Keycode key, GameCallback func) { + + // Apply input mappings. + + ++inputRegistered; + + // allocate space for current keys+1. + inputMappings = (SDL_Keycode*)realloc(inputMappings, sizeof(SDL_Keycode) * inputRegistered); + inputCallbacks = (GameCallback*)realloc(inputCallbacks, sizeof(GameCallback) * inputRegistered); + inputStates = (bool*)realloc(inputStates, sizeof(bool) * inputRegistered); + + // Actually apply the new callback + inputMappings[inputRegistered-1] = key; + inputCallbacks[inputRegistered-1] = func; + inputStates[inputRegistered-1] = false; + + // Return the index. + return inputRegistered-1; + } + + void ContextManager::RegisterMouse(MouseCallback func) { + mouseCallback = func; + } + + // Get input via abstract ID. + bool ContextManager::GetInput(int index) { + return inputStates[index]; + } + + // Remap abstract key. + void ContextManager::RemapKey(int index, SDL_Keycode to) { + // Check if something is already mapped to 'to'. + int reg = -1; + for(int i = 0; i < inputRegistered; i++) { + if(inputMappings[i] == to) { + reg = i; + } + } + // Remap, swap if necessary. + if(reg > -1) + inputMappings[reg] = inputMappings[index]; + inputMappings[index] = to; + } + + // Set Quit flag. + void ContextManager::SetQuit() { + this->StartQuit = true; + } + + bool ContextManager::GetQuit() { + return this->StartQuit; + } + + // Destroy context. + + ContextManager::~ContextManager() { + delete audioMgr; + SDL_DestroyWindow(window); + SDL_Quit(); + } + + // Gets the audio manager. + AudioManager* ContextManager::Audio() { + return audioMgr; + } + + // Gets the audio manager. + TextManager* ContextManager::Text() { + return txtMgr; + } + + void ContextManager::StartSync() { + timeElapsed = SDL_GetTicks(); + } + + void ContextManager::EndSync() { + while (1) { + double currentTime = SDL_GetTicks(); + if(currentTime - timeElapsed > 1000 / logicRate) + return; + SDL_Delay((1000 / logicRate) / 8); + } + } + + void ContextManager::SetTitle(char* title) { + SDL_SetWindowTitle(window, title); + } diff --git a/external/src/zero/TextManager.cpp b/external/src/zero/TextManager.cpp new file mode 100644 index 0000000..4109597 --- /dev/null +++ b/external/src/zero/TextManager.cpp @@ -0,0 +1,130 @@ +#include "Zero.hpp" + +TextManager::TextManager(ContextManager* ct) { + this->ctx = ct; + + if(TTF_Init() == -1) { + printf("TTF Init failed. %s\n", TTF_GetError()); + exit(-8); + } + + LoadFont((char*)"default.ttf"); + + color.r = 255; + color.g = 255; + color.b = 255; + color.a = 255; + +} + +TextManager::~TextManager() { + while(fonts_loaded > 0) { + TTF_CloseFont(fonts[fonts_loaded-1]); + --fonts_loaded; + } + + free(fonts); + + TTF_Quit(); +} + +int TextManager::LoadFont(char* fname) { + + ++fonts_loaded; + + fonts = (TTF_Font**)realloc(fonts, sizeof(TTF_Font*) * fonts_loaded); + + if ( !(fonts[fonts_loaded - 1] = TTF_OpenFont(fname, 20) ) ) { + printf("Font Open Failed. Load attempt: %s. Msg: %s\n", fname, TTF_GetError()); + } + + TTF_SetFontHinting(fonts[fonts_loaded - 1], TTF_HINTING_NONE); + + return fonts_loaded - 1; +} + + +// Implement properly later with wrapped coordinates. +void TextManager::Render(char* text) { + Render(text, 0, 0); +} + +void TextManager::Render(char* text, int x, int y) { + if (text == NULL || fonts[current_font] == NULL) + return; + + SDL_Surface *sf1 = NULL, *sf2 = NULL; + sf1 = TTF_RenderUTF8_Blended(fonts[current_font], text, color); + if(outline) { + SDL_Color n_color; + n_color.r = 255 - color.r; + n_color.g = 255 - color.g; + n_color.b = 255 - color.b; + n_color.a = color.a; + TTF_SetFontOutline(fonts[current_font], outline_px); + sf2 = TTF_RenderUTF8_Blended(fonts[current_font], text, n_color); + TTF_SetFontOutline(fonts[current_font], 0); + } + + SDL_Texture *tmp1 = NULL, *tmp2 = NULL; + + tmp1 = SDL_CreateTextureFromSurface(ctx->Renderer(), sf1); + if(outline) + tmp2 = SDL_CreateTextureFromSurface(ctx->Renderer(), sf2); + + SDL_Rect src, dst, src2, dst2; + src.x = 0; + src.y = 0; + src.w = sf1->w; + src.h = sf1->h; + + dst.x = x; + dst.y = y; + dst.w = src.w; + dst.h = src.h; + + if(outline) { + src2.x = 0; + src2.y = 0; + src2.w = sf2->w; + src2.h = sf2->h; + + dst2.x = x - (outline_px); + dst2.y = y - (outline_px); + dst2.w = src2.w; + dst2.h = src2.h; + SDL_FreeSurface(sf2); + ctx->OverlayBlit(tmp2, &src2, &dst2); + SDL_DestroyTexture(tmp2); + } + + SDL_FreeSurface(sf1); + ctx->OverlayBlit(tmp1, &src, &dst); + SDL_DestroyTexture(tmp1); + +} + +int TextManager::TestLen(char* text) { + int w, h; + TTF_SizeText(fonts[current_font], text, &w, &h); + + return w; +} + +void TextManager::Outline(int pixels) { + if(pixels == 0) { + outline = false; + } + else { + outline = true; + outline_px = pixels; + } +} + +void TextManager::SetColor(int r, int g, int b, int a) +{ + color.r = r; + color.g = g; + color.b = b; + color.a = a; +} diff --git a/external/src/zero/UDisplayable.cpp b/external/src/zero/UDisplayable.cpp new file mode 100644 index 0000000..c85c925 --- /dev/null +++ b/external/src/zero/UDisplayable.cpp @@ -0,0 +1,362 @@ +#include "Zero.hpp" + + // Creates a new Displayable. + // The mode is already Normal if we do nothing, so this constructor doesn't have to change. + UDisplayable::UDisplayable(ContextManager* cx, char* fname) { + + SDL_Surface* bitmap_tmp = IMG_Load(fname); + + if(!bitmap_tmp) { + printf("[UDisplayable::Ctor] File could not be loaded, this->Error set.\n"); + Error = true; + } + else { + this->x = 0; + this->y = 0; + this->loc.x = 0; + this->loc.y = 0; + this->ctx = cx; + this->frameWidth = bitmap_tmp->w; + this->bmp_w = bitmap_tmp->w; + this->bmp_h = bitmap_tmp->h; + + // We still allocate the two arrays, regardless. + + // These values are unused, but we'll default them so it will operate normally. + hitbox = (int*)calloc(sizeof(int), 4); + + // By default, it will fill this with 0, 0, W, H. + // This will behave identically to a displayable. + hitbox[0] = 0; + hitbox[1] = 0; + hitbox[2] = bitmap_tmp->w; + hitbox[3] = bitmap_tmp->h; + + this->loc.w = bitmap_tmp->w; + this->loc.h = bitmap_tmp->w; + + frame = (int*)calloc(sizeof(int), 4); + + frame[0] = 0; + frame[1] = 0; + frame[2] = cx->GetWidth(); + frame[3] = cx->GetHeight(); + + // Determine if we're on an accelerated context. If so, we create a texture out of the bitmap. + // Then we store what we'll use to the void* bitmap, either Tex or Surf. + + if (cx->Accelerated()) { + SDL_Texture* tex = SDL_CreateTextureFromSurface(ctx->Renderer(), bitmap_tmp); + this->bitmap = (void*)tex; + SDL_FreeSurface(bitmap_tmp); + } + else { + this->bitmap = (void*)bitmap_tmp; + } + } + #ifdef DEBUG_OVERKILL + printf("[UDisplayable~Ctor] accel:%d\n", cx->Accelerated()); + #endif + } + + // Sets the Displayable's mode. + UDisplayable::UDisplayable(ContextManager* cx, UDisplayableMode mode, char* fname) : UDisplayable(cx, fname) { + this->dispMode = mode; + } + + // Load from memory. + UDisplayable::UDisplayable(ContextManager* cx, UDisplayableMode mode, void* memory, int mSize) { + + SDL_RWops* rwo = SDL_RWFromMem(memory, mSize); + SDL_Surface* bitmap_tmp = IMG_LoadTyped_RW(rwo, 0, "PNG"); + if(rwo == NULL || bitmap_tmp == NULL) { + printf("Loading RWops failed. %s", SDL_GetError()); + while(1); + //exit(-1); + } + + this->x = 0; + this->y = 0; + this->loc.x = 0; + this->loc.y = 0; + this->ctx = cx; + this->frameWidth = bitmap_tmp->w; + this->bmp_w = bitmap_tmp->w; + this->bmp_h = bitmap_tmp->h; + + // We still allocate the two arrays, regardless. + + // These values are unused, but we'll default them so it will operate normally. + hitbox = (int*)calloc(sizeof(int), 4); + + // By default, it will fill this with 0, 0, W, H. + // This will behave identically to a displayable. + hitbox[0] = 0; + hitbox[1] = 0; + hitbox[2] = bitmap_tmp->w; + hitbox[3] = bitmap_tmp->h; + + this->loc.w = bitmap_tmp->w; + this->loc.h = bitmap_tmp->w; + + frame = (int*)calloc(sizeof(int), 4); + + frame[0] = 0; + frame[1] = 0; + frame[2] = cx->GetWidth(); + frame[3] = cx->GetHeight(); + + // Determine if we're on an accelerated context. If so, we create a texture out of the bitmap. + // Then we store what we'll use to the void* bitmap, either Tex or Surf. + + if (cx->Accelerated()) { + SDL_Texture* tex = SDL_CreateTextureFromSurface(ctx->Renderer(), bitmap_tmp); + this->bitmap = (void*)tex; + SDL_FreeSurface(bitmap_tmp); + } + else { + this->bitmap = (void*)bitmap_tmp; + } + + this->dispMode = mode; + } + + // Sets the position on screen. + + void UDisplayable::SetXY(double x, double y) { + if (Error) + return; + this->x = x; + this->y = y; + + // Expand that logic above. + + if(this->x < 0) + this->x = 0; + if(this->y < 0) + this->y = 0; + + if(frameIndex == -1) { + if(this->x > frame[2] - this->bmp_w) + this->x = (double)(frame[2] - this->bmp_w); + } + else { + if(this->x > frame[2] - this->frameWidth) + this->x = (double)(frame[2] - this->frameWidth); + } + + if(this->y > frame[3] - this->bmp_h) + this->y = (double)(frame[3] - this->bmp_h); + + this->loc.x = (int)this->x; + this->loc.y = (int)this->y; + + #ifdef DEBUG_OVERKILL + printf("[UDisplayable::SetXY] x:%d y:%d w:%d h:%d\n", frame[0], frame[1], frame[2], frame[3]); + #endif + } + + // Modifies the position on screen. Meant to avoid embedded retrievals. + + void UDisplayable::ModXY(double x, double y) { + if (Error) + return; + + this->x += x; + this->y += y; + + // Expand that logic above. + + if(this->x < 0) + this->x = 0; + if(this->y < 0) + this->y = 0; + + if(frameIndex == -1) { + if(this->x > frame[2] - this->bmp_w) + this->x = (double)(frame[2] - this->bmp_w); + } + else { + if(this->x > frame[2] - this->frameWidth) + this->x = (double)(frame[2] - this->frameWidth); + } + + if(this->y > frame[3] - this->bmp_h) + this->y = (double)(frame[3] - this->bmp_h); + + this->loc.x = (int)this->x; + this->loc.y = (int)this->y; + + #ifdef DEBUG_OVERKILL + printf("[UDisplayable::SetXY] x:%d y:%d w:%d h:%d\n", frame[0], frame[1], frame[2], frame[3]); + #endif + } + + // Get X coord. + + double UDisplayable::GetX() { + if (Error) + return 0; + + return this->x; + } + + // Get Y coord. + + double UDisplayable::GetY() { + if (Error) + return 0; + return this->y; + } + + // Get aligned X coord. + + int UDisplayable::GetXI() { + if (Error) + return 0; + return this->loc.x; + } + + // Get aligned Y coord. + + int UDisplayable::GetYI() { + if (Error) + return 0; + return this->loc.y; + } + + // Blit to an associated context. + + void UDisplayable::Blit() { + if (Error) + return; + + // Copy loc and alter position. + SDL_Rect loc_adj; + loc_adj.x = loc.x + frame[0]; + loc_adj.y = loc.y + frame[1]; + loc_adj.w = frameWidth; + loc_adj.h = bmp_h; + + #ifdef DEBUG_OVERKILL + printf("[UDisplayable::Blit]\n"); + #endif + + if (frameIndex == -1) { + ctx->Blit(bitmap, NULL, &loc_adj); + return; + } + + SDL_Rect frameClip; + + frameClip.x = frameWidth * frameIndex; + frameClip.y = 0; + frameClip.w = frameWidth; + frameClip.h = bmp_h; + + ctx->Blit(bitmap, &frameClip, &loc_adj); + } + + // Get SDL_Rect for collision calculation. In a base Displayable, it returns the image width. + // In a derived class, it may return only a hitbox. + + int* UDisplayable::GetHitbox() { + if (Error) + return NULL; + int* rect = (int*)calloc(sizeof(int), 4); + + rect[0] = hitbox[0] + (int)this->x; + rect[1] = hitbox[1] + (int)this->y; + rect[2] = hitbox[2]; + rect[3] = hitbox[3]; + + return rect; + } + + // Destroy bitmap. + + UDisplayable::~UDisplayable() { + if (Error) + return; + if(ctx->Accelerated()) + SDL_DestroyTexture((SDL_Texture*)bitmap); + else + SDL_FreeSurface((SDL_Surface*)bitmap); + free(hitbox); + free(frame); + } + + void UDisplayable::SetHitbox(int x, int y, int w, int h) { + if (Error) + return; + if(dispMode == Normal || dispMode == Docked || dispMode == Anim || dispMode == AnimDocked) + return; + + hitbox[0] = x; + hitbox[1] = y; + hitbox[2] = w; + hitbox[3] = h; + } + + void UDisplayable::SetDock(int x, int y, int w, int h) { + if (Error) + return; + if(dispMode == Normal || dispMode == Hitbox || dispMode == Anim || dispMode == AnimHitbox) + return; + frame[0] = x; + frame[1] = y; + frame[2] = w; + frame[3] = h; + } + + void UDisplayable::NextFrame() { + if (Error) + return; + if (dispMode == Normal || dispMode == Hitbox || dispMode == Docked || dispMode == HitboxDocked) + return; + + ++frameIndex; + + if(frameWidth * frameIndex >= bmp_w) + frameIndex = 0; + } + + void UDisplayable::NextFrame(int f) { + if (Error) + return; + if (dispMode == Normal || dispMode == Hitbox || dispMode == Docked || dispMode == HitboxDocked) + return; + frameIndex += f; + + if(frameWidth * frameIndex >= bmp_w) + frameIndex = 0; + } + + void UDisplayable::ResetFrame() { + if (Error) + return; + if (dispMode == Normal || dispMode == Hitbox || dispMode == Docked || dispMode == HitboxDocked) + return; + frameIndex = 0; + } + + void UDisplayable::SetFrame(int f) { + if (Error) + return; + if (dispMode == Normal || dispMode == Hitbox || dispMode == Docked || dispMode == HitboxDocked) + return; + + frameIndex = f; + } + + void UDisplayable::SetFrameWidth(int frameW) { + if (Error) + return; + if (dispMode == Normal || dispMode == Hitbox || dispMode == Docked || dispMode == HitboxDocked) + return; + this->frameWidth = frameW; + + #ifdef DEBUG_OVERKILL + printf("[UDisplayable::SetFrameWidth] fW:%d\n", frameW); + #endif + } diff --git a/mk b/mk new file mode 100755 index 0000000..a78c48a --- /dev/null +++ b/mk @@ -0,0 +1,62 @@ +#!/bin/bash + +# This is all auxillary functions to simplify the build script. +# I hate makefiles, and cmake so shell scripts work. + +CXX="g++" +CXXFLAGS="$CXXFLAGS -fPIC -std=gnu++11 -Wall -Werror -Wno-error=pointer-arith" +LD="g++" +LDFLAGS="-fPIC -L$LIB $LDFLAGS -lSDL2 -lSDL2_image -lSDL2_mixer -lSDL2_ttf" +AR="ar rcs" +GEN="/bin/bash ./gen.sh" + +CXX_CMD="$CXX $CXXFLAGS" +LD_CMD="$LD $LDFLAGS" +CA_CMD="$CXX $CXXFLAGS $LDFLAGS" + +FILES=$2 + +function mkcc_ { + echo "CXX $2" + $CXX_CMD $INCLUDE -c $1 -o $2 +} + +function mkld_ { + echo "LD $2" + $LD_CMD $1 -o $2 +} + +function mkgen_ { + echo "GEN $1" + bash -c "cd ../$1 && $GEN" +} + +function mkcc { + mkcc_ $SRC/$1/$2.cpp $2.cpp.o +} + +function mkmcc { + for f in `ls $SRC/$1/*.cpp`; do + mkcc_ $f $(basename $f).o + done +} + +function mkld { + echo "LD $1" + $LD_CMD ./*.o $LIB/*.a -o $BIN/$1 +} + +function mkar { + echo "AR $1" + $AR $LIB/$1.a ./*.o +} + +function newtd { + mkdir td + cd td +} + +function deltd { + cd .. + rm -rf td +} diff --git a/vndc/include/Data.hpp b/vndc/include/Data.hpp new file mode 100644 index 0000000..75deede --- /dev/null +++ b/vndc/include/Data.hpp @@ -0,0 +1,45 @@ +#ifndef DATAGUARD_HPP +#define DATAGUARD_HPP + +#include +#include + +class DataContainer { + public: + ContextManager* ctx; + bool if_fail = false; + bool wait_input = false; + char current_scr[400], current_music[400], current_bg[400]; + int screen_w = 800; + int screen_h = 600; + int physical_w = 800; + int physical_h = 600; + int render_x1 = screen_w / 15; + int render_y1 = screen_h / 15; + int render_x2 = screen_w / 15 * 14; + int render_y2 = screen_h / 15 * 13; + int text_x = render_x1; + int text_y = render_y1; + std::map *g_flags = NULL; + std::map *s_flags = NULL; + bool jumped = false; + int* choice_coords = NULL; + int choices = 0; + FILE* accessScriptHandle = NULL; + char** main_scr; // Default value. + bool vndc_enabled = true; + bool is_spoken_line = false; + bool debug_mode = false; + bool debug_to_shell = false; + bool verbose = false; + int currentLine = 0; + bool skip_key_on = false; + char* window_name; +}; + +DataContainer* GetData(); +void CreateDataContainer(); +void DumpSave(char* fname); +void DumpSystemSave(char* fname); + +#endif diff --git a/vndc/include/Funcs.hpp b/vndc/include/Funcs.hpp new file mode 100644 index 0000000..21b5452 --- /dev/null +++ b/vndc/include/Funcs.hpp @@ -0,0 +1,38 @@ +#ifndef FUNCS_HPP +#define FUNCS_HPP + +#include +#include +#include +#include + +#include "Data.hpp" + +void Parse(); // This reads commands from files. +void ParseShell(); // This reads commands from the shell. +void ParseCmd(char* line); // This does the heavy lifting. +void Loop(); +void Wait(); +void Setup(); + +void InputAdvance(int x, int y, bool down, bool left, bool middle, bool right); +void QuitKey(bool down); +void NopKey(bool down); + +void op_bgload(char* file, int* fadetime); +void op_cleartext(); +void op_delay(int* frames); +void op_fi(); +void op_gsetvar(char* var, int *modifier, int *value); +void op_if(char* var, int* op, int* val); +void op_music(char* file); +void op_random(char* var, int* low, int* high); +void op_setimg(char* file, int* x, int* y); +void op_setvar(char* var, int *modifier, int *value); +void op_sound(char* file, int* times); +void op_text(char* string); +void op_jump(char* file, int* lineTo, bool isSave); +void op_goto(char* label); +void op_choice(char* choices); + +#endif diff --git a/vndc/src/Data.cpp b/vndc/src/Data.cpp new file mode 100644 index 0000000..ca78a49 --- /dev/null +++ b/vndc/src/Data.cpp @@ -0,0 +1,59 @@ +#include "Zero.hpp" + +#include "Funcs.hpp" + +DataContainer* data = NULL; + +const char* loadup = "script/main.scr"; + +void CreateDataContainer() { + data = new DataContainer(); + GetData()->main_scr = (char**)calloc(sizeof(char*), 1); + GetData()->main_scr[0] = (char*)calloc(sizeof(char), 400); + strncpy(GetData()->main_scr[0], loadup, 400); +} + +DataContainer* GetData() { + return &data[0]; +} + +void DumpSave(char* fname) { + // Dump variables. + // Dump script file. + + // A save actually ends up as a mini-script. + // So, to load a save you load this as the + // main script + // For example: + // setvar data1 = 6 + // setvar data2 = 9 + // music mus + // bgload bg + // jump script.scr 60 + // The call command runs a scr, and returns here. + + FILE* save_to = fopen(fname, "w"); + + std::map data_vals = GetData()->s_flags[0]; + + if(!data_vals.empty()) { + std::map::iterator item = data_vals.begin(); + while(item != data_vals.end()) { + fprintf(save_to, "setvar %s = %d\n", item->first.c_str(), item->second); + + ++item; + } + } + + fprintf(save_to, "music %s\n", &(GetData()->current_music[6])); + fprintf(save_to, "bgload %s\n", &(GetData()->current_bg[11])); + fprintf(save_to, "jump %s %d\n", &(GetData()->current_scr[7]), GetData()->currentLine - 1); // The text never completely displayed + // So restore back one to replay + + fclose(save_to); +} +void DumpSystemSave(char* fname) { + // A system save is simply a script + // with only gsetvar. + // It is automatically run if it exists +} diff --git a/vndc/src/Loop.cpp b/vndc/src/Loop.cpp new file mode 100644 index 0000000..7be1d01 --- /dev/null +++ b/vndc/src/Loop.cpp @@ -0,0 +1,66 @@ +#include "Zero.hpp" + +#include "Funcs.hpp" + +void Wait() { + // If wait wasn't specified, don't halt. + // Don't even bother with extensions off. + // If we're currently in a quote, leave it alone. + // If the line is spoken, then halt previous spoken lines. + // If the skip key is held, just gogogo + + bool stop_voice = GetData()->wait_input && GetData()->vndc_enabled; + + while((GetData()->wait_input && !GetData()->ctx->GetQuit())) { + GetData()->ctx->Input(); + + GetData()->ctx->Flush(); + + if(GetData()->debug_to_shell) + ParseShell(); + + if(GetData()->ctx->GetInput(1)) break; + } + + if(stop_voice) + op_sound((char*)"~", NULL); + +} + +void Loop() { + if(GetData()->ctx->GetQuit()) return; + Parse(); + + // We don't clear. This system uses dirty blits. ;P + GetData()->ctx->Flush(); + + GetData()->ctx->StartSync(); + + Wait(); + + GetData()->ctx->EndSync(); +} + +void Setup() { + // Init window + GetData()->ctx->InitWindowLogical(GetData()->physical_w, GetData()->physical_h, GetData()->screen_w, GetData()->screen_h, false, true); + + GetData()->window_name = (char*)calloc(sizeof(char), 400); + sprintf(GetData()->window_name, "%s", "VNDC Interpreter "); + GetData()->ctx->SetTitle(GetData()->window_name); + + GetData()->ctx->InputMode(Burst); + + // Input + GetData()->ctx->RegisterMouse(&InputAdvance); + GetData()->ctx->RegisterInput(SDLK_ESCAPE, &QuitKey); + GetData()->ctx->RegisterInput(SDLK_LCTRL, &NopKey); + + GetData()->s_flags = new std::map(); + GetData()->g_flags = new std::map(); + + GetData()->ctx->Text()->Outline(2); + GetData()->ctx->Text()->SetColor(255,255,255,255); + + op_cleartext(); +} diff --git a/vndc/src/Parse.cpp b/vndc/src/Parse.cpp new file mode 100644 index 0000000..6b6d7d9 --- /dev/null +++ b/vndc/src/Parse.cpp @@ -0,0 +1,268 @@ +#include "Zero.hpp" + +#include "Data.hpp" + +#include "Funcs.hpp" + +void ParseCmd(char* line) { + + char *passthru_line = (char*)calloc(sizeof(char), 400); + + char** tokens = NULL; + + // Remove all '\n' from this string + for(int i=0; i < 400; i++) { + if (line[i] == '\n') + line[i] = '\0'; + } + + strncpy(passthru_line, line, sizeof(char)*400); + + if(GetData()->verbose) printf("[scr] %s\n", line); + + int num = 1; + tokens = (char**)realloc(NULL, sizeof(char*) * (1)); + tokens[num-1] = strtok(line, " "); + + do { + #ifdef DEBUG_OVERKILL + printf("Loop: num = %d;\n", num); + #endif + ++num; + tokens = (char**)realloc(tokens, sizeof(char*) * (num)); + tokens[num-1] = strtok(NULL, " "); + } while(tokens[num-1] != NULL); + + --num; + + //printf("Made it out of the loop.\n"); + //for (int i = 0; i < num; i++) { + //printf("[param] %d = '%s'\n", i, tokens[i]); + //} + + int value_1, value_2; + + if(!strcmp(tokens[0], "bgload")) { + //printf("[OP::bgload] exec (params:%d)", num-1); + if (num > 2) { + sscanf(tokens[2], "%d", &value_1); + op_bgload(tokens[1], &value_1); + } + else + op_bgload(tokens[1], NULL); + } + else if(!strcmp(tokens[0], "setimg")) { + sscanf(tokens[2], "%d", &value_1); + sscanf(tokens[3], "%d", &value_2); + op_setimg(tokens[1], &value_1, &value_2); + } + else if(!strcmp(tokens[0], "sound")) { + // Another ridiculous thing. Second parameter if not + // specified is implicity one + if(num > 2) { + sscanf(tokens[2], "%d", &value_1); + op_sound(tokens[1], &value_1); + } + else + op_sound(tokens[1], NULL); + } + else if(!strcmp(tokens[0], "music")) + op_music(tokens[1]); + else if(!strcmp(tokens[0], "text")) { + // Because of *reasons* (lack of quotes) we use the copy of line, + // passthru_line and adjust the pointer to use that. + // strtok destroys the structure + // And there's the possibility of a zero-length string as well. + //printf("[op_text] Reconstructed string = '%s'\n", &passthru_line[5]); + op_text(&passthru_line[5]); + } + else if(!strcmp(tokens[0], "choice")) { + op_choice(&passthru_line[7]); + } + else if(!strcmp(tokens[0], "setvar")) { + if(num > 3) { + if(!strcmp(tokens[2], "=")) + value_1 = 0; + else if(!strcmp(tokens[2], "+")) + value_1 = 1; + else if(!strcmp(tokens[2], "-")) + value_1 = -1; + else if(!strcmp(tokens[2], "~")) // Apparently resets. UGH NOT DOC'D + value_1 = -2; + + + sscanf(tokens[3], "%d", &value_2); + op_setvar(tokens[1], &value_1, &value_2); + } + else { + value_1 = -2; + op_setvar(tokens[1], &value_1, NULL); + } + } + else if(!strcmp(tokens[0], "gsetvar")) { + if(!strcmp(tokens[2], "=")) + value_1 = 0; + else if(!strcmp(tokens[2], "+")) + value_1 = 1; + else if(!strcmp(tokens[2], "-")) + value_1 = -1; + + sscanf(tokens[3], "%d", &value_2); + op_gsetvar(tokens[1], &value_1, &value_2); + } + else if(!strcmp(tokens[0], "if")) { + if(!strcmp(tokens[2], "<=")) + value_1 = 0; + else if(!strcmp(tokens[2], "<")) + value_1 = 1; + else if(!strcmp(tokens[2], "==")) + value_1 = 2; + else if(!strcmp(tokens[2], "!=")) + value_1 = 3; + else if(!strcmp(tokens[2], ">")) + value_1 = 4; + else if(!strcmp(tokens[2], ">=")) + value_1 = 5; + + sscanf(tokens[3], "%d", &value_2); + op_if(tokens[1], &value_1, &value_2); + } + else if(!strcmp(tokens[0], "fi")) + op_fi(); + else if(!strcmp(tokens[0], "jump")) { + if(num > 2) { + sscanf(tokens[2], "%d", &value_1); + op_jump(tokens[1], &value_1, false); + } + else + op_jump(tokens[1], NULL, false); + } + else if(!strcmp(tokens[0], "delay")) { + sscanf(tokens[1], "%d", &value_1); + op_delay(&value_1); + } + else if(!strcmp(tokens[0], "random")) { + sscanf(tokens[2], "%d", &value_1); + sscanf(tokens[3], "%d", &value_2); + op_random(tokens[1], &value_1, &value_2); + } + else if(!strcmp(tokens[0], "goto")) + op_goto(tokens[1]); + else if(!strcmp(tokens[0], "label")) {} + // Nuthin. + else if(!strcmp(tokens[0], "cleartext")) + op_cleartext(); + + free(tokens); + free(passthru_line); +} + +void ParseShell() { + bool DebugContinue = true; + char buffer[400]; + while(DebugContinue) { + memset(buffer, 0, sizeof(char)*400); + + printf("[scr command] $ "); + fgets(buffer, 400, stdin); + + // Remove all '\n' from this string + for(int i=0; i < 400; i++) { + if (buffer[i] == '\n') + buffer[i] = '\0'; + } + + if(!strcmp(buffer, "help") || strlen(buffer) < 1) { + printf("%s\n", "Commands available:"); + printf("\t%s\t\t\t%s\n", "(debug) stop", "Stops debug mode"); + printf("\t%s\t\t\t%s\n", "(debug) quit", "Quits game"); + printf("\t%s\t\t%s\n", "(debug) save [file]", "Saves immediately to file"); + printf("\t%s\t%s\n", "setvar [var] [mod] [val]", "Set save flag"); + printf("\t%s\t%s\n", "gsetvar [var] [mod] [val]", "Set system flag"); + printf("\t%s\t\t\t%s\n", "text [text] ...", "Display text"); + printf("\t%s\t\t%s\n", "sound [file] (num)", "Play sound num times"); + printf("\t%s\t\t\t%s\n", "music [file]", "Play music"); + printf("\t%s\t\t%s\n", "setimg [file] [x] [y]", "Display image at x,y"); + printf("\t%s\t%s\n", "random [var] [low] [high]", "Store random number in var"); + printf("\t%s\t\t%s\n", "jump [file.scr] {N}", "Switch to file.src (goto line N)"); + printf("\t%s\t\t\t%s\n", "goto [label]", "Goto label in current file"); + printf("\t%s\t\t%s\n", "if [var] [op] [val]", "Test condition, and execute till\n\t\t\t\t\tfi if true"); + printf("\t%s\t\t\t\t%s\n", "fi", "Stop computing if"); + printf("\t%s\t\t\t%s\n", "delay [frames]", "Delay frames (at 60fps)"); + printf("\t%s\t\t\t%s\n", "cleartext", "Clear text from screen"); + printf("\t%s\t%s\n", "choice [ch|ch|...] {ctx->SetQuit(); + DebugContinue = false; + } + else if (!strcmp(buffer, "stop")) { + printf("[debug] Exiting debug shell and resuming.\n"); + DebugContinue = false; + GetData()->wait_input = true; + } + else if (!strncmp(buffer, "save", 4)) { + char* savefile = &buffer[5]; + printf("[debug] Saving to file '%s' NOW.\n", savefile); + DumpSave(savefile); + } + else { + ParseCmd(buffer); + GetData()->ctx->Flush(); + GetData()->wait_input = false; + } + } + GetData()->debug_to_shell = false; +} + +void Parse() { + if(GetData()->ctx->GetQuit()) return; + + ++(GetData()->currentLine); + + if (!GetData()->accessScriptHandle) { + fprintf(stderr, "Could not open script data\n"); + exit(-8); + } + + char *line = (char*)calloc(sizeof(char), 400); + + fgets(line, 400, GetData()->accessScriptHandle); + + ParseCmd(line); + + free(line); + + if(feof(GetData()->accessScriptHandle)) { + op_jump(GetData()->main_scr[0], NULL, true); + } + + return; +} + +void InputAdvance(int x, int y, bool down, bool left, bool middle, bool right) { + if(GetData()->choices > 0) { + // Choose an option. + for(int i=0; ichoices; i++) { + if(!down && y > GetData()->choice_coords[i*2] && y < GetData()->choice_coords[i*2+1]) + { + GetData()->choices = -(i+1); // Negative indicates complete. This is just + // for storage savings. + } + } + } + else if(left && !down) { + GetData()->wait_input = false; + } +} + +void QuitKey(bool down) { + // Flush data to save.scr + DumpSave((char*)"save.scr"); + + GetData()->ctx->SetQuit(); +} + +void NopKey(bool down) {} diff --git a/vndc/src/VNDC.cpp b/vndc/src/VNDC.cpp new file mode 100644 index 0000000..f3301a2 --- /dev/null +++ b/vndc/src/VNDC.cpp @@ -0,0 +1,115 @@ +#include "Zero.hpp" + +#include "Funcs.hpp" + +#include +#include + + + +void DebugTrap(int sig) { + GetData()->debug_to_shell = true; +} + +int main(int argc, char** argv) { + printf(" ___________________________________________________________ \n"); + printf("| VNDC v0.0.1 - VNDC is Not a Direct Clone (of VNDS ;P) |\n"); + printf("| Interprets VNDS scripts with a few goodies and extensions |\n"); + printf("| (C) Jonathan Feldman 2014 - Under the MIT license |\n"); + printf("|___________________________________________________________|\n\n"); + + char* chdir_to_dir = NULL; + char* main_script_override = NULL; + char* save_file = NULL; + bool vndc_extensions = true; + int width = 0, height = 0; + bool debug_enable = false; + bool enable_v = false; + char c; + + while((c = getopt(argc, argv, "bvx:y:d:m:s:ch")) != -1) { + switch(c) { + case 'v': + printf("[info] Script commands will be echoed.\n"); + enable_v = true; + break; + case 'b': + printf("[debug] Debug Mode enabled.\n"); + debug_enable = true; + break; + case 'd': + printf("[info] Directory specified: %s\n", optarg); + chdir_to_dir = optarg; + break; + case 'x': + sscanf(optarg, "%d", &width); + break; + case 'y': + sscanf(optarg, "%d", &height); + chdir_to_dir = optarg; + break; + case 'm': + printf("[debug] Main script overriden as: '%s'\n", optarg); + main_script_override = optarg; + break; + case 's': + printf("[info] Load save: '%s'\n", optarg); + save_file = optarg; + break; + case 'c': + printf("[debug] Compliant mode: all VNDC extensions off\n"); + vndc_extensions = false; + break; + case 'h': + printf("-x size -y size\t\tSet display window to wxh\n"); + printf("-d dir\t\tChange to directory/Run game in directory\n"); + printf("-b\t\tDebug Mode. Hit Ctrl+C on console for shell\n"); + printf("-v\t\tVerbose. Echo script commands back as they execute\n"); + printf("-m .scr\t\tLoad .scr as main script\n"); + printf("-s .scr\t\tLoad save .scr\n"); + printf("-c\t\tCompliant mode; don't use VNDC extensions\n"); + printf("-h\t\tPrint this help message\n"); + return 0; + break; + default: + break; + } + } + + CreateDataContainer(); + + GetData()->ctx = new ContextManager(); + + if(chdir_to_dir) + chdir(chdir_to_dir); + if(main_script_override != NULL) { + printf("[debug] Note that in this mode, l_flags is not set.\n[debug] Expect bugs/gameover, this is normal.\n"); + memset(GetData()->main_scr[0], 0, 399); + strncpy(GetData()->main_scr[0], main_script_override, 399); + } + GetData()->vndc_enabled = vndc_extensions; + GetData()->verbose = enable_v; + if(debug_enable) { + signal(SIGINT, DebugTrap); + GetData()->debug_mode = true; + } + + if(width > 0 && height > 0) { + GetData()->physical_w = width; + GetData()->physical_h = height; + } + + Setup(); + + if(!save_file) + op_jump(GetData()->main_scr[0], NULL, true); + else + op_jump(save_file, NULL, true); + + while(!(GetData()->ctx->GetQuit())) { + Loop(); + } + + delete GetData()->ctx; + delete GetData(); +} diff --git a/vndc/src/op_bgload.cpp b/vndc/src/op_bgload.cpp new file mode 100644 index 0000000..a6ad33a --- /dev/null +++ b/vndc/src/op_bgload.cpp @@ -0,0 +1,45 @@ +#include "Zero.hpp" + +#include "Funcs.hpp" + +/* + * Implements bgload vnds function. + * bgload file [fadetime] (default 16) + */ + +void op_bgload(char* file, int* fadetime) { + if (GetData()->if_fail || GetData()->ctx->GetQuit()) + return; + + // Fadeout not implemented yet. + + memset(GetData()->current_bg, 0, 400); + + snprintf(GetData()->current_bg, 400, "background/%s", file); + + //printf("Attempt to load file %s as BG\n", path); + + // Load displayable. + SDL_Surface* sfc = IMG_Load(GetData()->current_bg); + + uint8_t transp_incr = 16; + if(fadetime != NULL) + transp_incr = 255 / *fadetime; + + // Transition effect. + + SDL_Texture* tx = NULL; + tx = SDL_CreateTextureFromSurface(GetData()->ctx->Renderer(), sfc); + SDL_SetTextureBlendMode(tx, SDL_BLENDMODE_BLEND); + + SDL_FreeSurface(sfc); + + int delay = 1; + for(int tr = 0; tr < 255; tr += transp_incr) { + SDL_SetTextureAlphaMod(tx, tr); + GetData()->ctx->Blit(tx, NULL, NULL); + op_delay(&delay); + } + + SDL_DestroyTexture(tx); +} diff --git a/vndc/src/op_choice.cpp b/vndc/src/op_choice.cpp new file mode 100644 index 0000000..2c5e01e --- /dev/null +++ b/vndc/src/op_choice.cpp @@ -0,0 +1,100 @@ +#include "Zero.hpp" + +#include "Funcs.hpp" + +/* + * Implements choice vnds function. + * choice choicest1|choicest2|... [>var] + * [>var] is an extension of this dialect + * which stores the result into a specific variable + * The default will still be 'selected' if not specified + */ + +void op_choice(char* line) { + if (GetData()->if_fail) + return; + // Strtok by the pipe '|' character + + //printf("%s\n", line); + + int num = 1; + char** tokens = (char**)realloc(NULL, sizeof(char*) * (1)); + tokens[num-1] = strtok(line, "|"); + + do { + //printf("Loop: num = %d;\n", num); + ++num; + tokens = (char**)realloc(tokens, sizeof(char*) * (num)); + tokens[num-1] = strtok(NULL, "|"); + } while(tokens[num-1] != NULL); + + --num; + + /*for(int i=0; i' is there. + + char varname[400]; + memset(varname, 0, 400); + int defaultname = 0; + + if(GetData()->vndc_enabled) { // This is an extension. + for( int i = strlen(tokens[num-1]); i >= 0; i-- ) { + if(tokens[num-1][i] == '>') { + // Yes there is. + defaultname = i + 1; + tokens[num-1][i] = '\0'; + break; + } + } + } + + if(defaultname > 0) { + strncpy(varname, &tokens[num-1][defaultname], 400); + } + else { + strncpy(varname, "selected", 400); + } + + // For each choice, we need to print text and make a click area. This will use the text function. + int *choices = (int*)calloc(sizeof(int), num * 2); + + for(int i=0; i < num*2; i+=2) { + choices[i] = GetData()->text_y; + char* outarr = (char*)calloc(sizeof(char*), strlen(tokens[i/2])+3); + outarr[0] = '0' + (i/2); + outarr[1] = '.'; + outarr[2] = ' '; + strncpy(&outarr[3], tokens[i/2], strlen(tokens[i/2])); + op_text(outarr); + free(outarr); + choices[i+1] = GetData()->text_y; + } + + GetData()->choice_coords = choices; + GetData()->choices = num; + + while(GetData()->choices > 0) { + if(GetData()->ctx->GetQuit()) goto killed; + + GetData()->ctx->Flush(); + + GetData()->ctx->StartSync(); + GetData()->ctx->Input(); + GetData()->ctx->EndSync(); + } + + // Get the chosen option and load it to a variable (abs of course) + + GetData()->s_flags[0][std::string(varname)] = -(GetData()->choices); + + // Clear after choices. Period. + op_cleartext(); + +killed: + + // Also reset the 'need to click' since we just did. + GetData()->wait_input = false; +} diff --git a/vndc/src/op_cleartext.cpp b/vndc/src/op_cleartext.cpp new file mode 100644 index 0000000..d05f9cd --- /dev/null +++ b/vndc/src/op_cleartext.cpp @@ -0,0 +1,52 @@ +#include "Zero.hpp" + +#include "Funcs.hpp" + +void ct_transwindow() { + + int width_dr = (GetData()->render_x2 - GetData()->render_x1 + 20); + int height_dr = (GetData()->render_y2 - GetData()->render_y1 + 30 + 20); + + SDL_Surface* sfc = SDL_CreateRGBSurface(0, width_dr, height_dr, 32, 0, 0, 0, 0); + SDL_FillRect(sfc, NULL, SDL_MapRGBA(sfc->format, 0, 0, 0, 128)); + + SDL_Rect src; + src.x = 0; + src.y = 0; + src.w = sfc->w; + src.h = sfc->h; + + SDL_Texture* dim = SDL_CreateTextureFromSurface(GetData()->ctx->Renderer(), sfc); + SDL_SetTextureBlendMode(dim, SDL_BLENDMODE_BLEND); + SDL_SetTextureAlphaMod(dim, 128); + + SDL_FreeSurface(sfc); + + SDL_Rect dst; + dst.x = GetData()->render_x1 - 10; + dst.y = GetData()->render_y1 - 10; + dst.w = src.w; + dst.h = src.h; + + GetData()->ctx->OverlayBlit(dim, &src, &dst); + + SDL_DestroyTexture(dim); +} + +/* + * Implements cleartext vnds function. + * cleartext mod + * However, we ignore mod for now. + */ + +void op_cleartext() { + if (GetData()->if_fail || GetData()->ctx->GetQuit()) + return; + + GetData()->text_x = GetData()->render_x1; + GetData()->text_y = GetData()->render_y1; + GetData()->ctx->ClearOverlay(); + + // Dim transparent overlay + ct_transwindow(); +} diff --git a/vndc/src/op_delay.cpp b/vndc/src/op_delay.cpp new file mode 100644 index 0000000..c032c10 --- /dev/null +++ b/vndc/src/op_delay.cpp @@ -0,0 +1,18 @@ +#include "Zero.hpp" + +#include "Funcs.hpp" + +/* + * Implements delay vnds function. + * delay frames + */ + +void op_delay(int* frames) { + if (GetData()->if_fail || GetData()->ctx->GetQuit()) + return; + for(int i = 0; i < *frames; i++) { + // This is one frame. + GetData()->ctx->StartSync(); + GetData()->ctx->EndSync(); + } +} diff --git a/vndc/src/op_fi.cpp b/vndc/src/op_fi.cpp new file mode 100644 index 0000000..ec4af942 --- /dev/null +++ b/vndc/src/op_fi.cpp @@ -0,0 +1,12 @@ +#include "Zero.hpp" + +#include "Funcs.hpp" + +/* + * Implements fi vnds function. + * if var op val + */ + +void op_fi() { + GetData()->if_fail = false; +} diff --git a/vndc/src/op_goto.cpp b/vndc/src/op_goto.cpp new file mode 100644 index 0000000..d620e79 --- /dev/null +++ b/vndc/src/op_goto.cpp @@ -0,0 +1,50 @@ +#include "Zero.hpp" + +#include "Funcs.hpp" + +/* Implements vnds goto function + * goto label + * File pointer is provided so we can rewind. + */ + +void op_goto(char* label) { + FILE** infile = &(GetData()->accessScriptHandle); + + if (GetData()->if_fail || GetData()->ctx->GetQuit()) + return; + rewind(*infile); + + char *line = (char*)calloc(sizeof(char), 400); + + int line_to = 0; + + bool found = false; + while(!found) { + line_to++; + fgets(line, 400, *infile); + + // Remove all '\n' from this string + for(int i=0; i < 400; i++) { + if (line[i] == '\n') + line[i] = '\0'; + } + + int num = 1; + char** tokens = (char**)realloc(NULL, sizeof(char*) * (1)); + tokens[num-1] = strtok(line, " "); + + do { + //printf("Loop: num = %d;\n", num); + ++num; + tokens = (char**)realloc(tokens, sizeof(char*) * (num)); + tokens[num-1] = strtok(NULL, " "); + } while(tokens[num-1] != NULL); + + --num; + + if(!strcmp(tokens[0], "label")) + if(!strcmp(tokens[1], label)) + found = true; + } + GetData()->currentLine = line_to; +} diff --git a/vndc/src/op_gsetvar.cpp b/vndc/src/op_gsetvar.cpp new file mode 100644 index 0000000..01f0bed --- /dev/null +++ b/vndc/src/op_gsetvar.cpp @@ -0,0 +1,25 @@ +#include "Zero.hpp" + +#include "Funcs.hpp" + +/* + * Implements gsetvar vnds function. + * gsetvar var mod val + * Modifier is '=' '+' or '-' in script, simplify to ('-':-1, '=':0, '+':1). + * MAY need to be UTF8 friendly + */ + +void op_gsetvar(char* var, int *modifier, int *value) { + if (GetData()->if_fail) + return; + + if(*modifier == 0) { + GetData()->g_flags[0][std::string(var)] = value[0]; + } + else if (*modifier == -1) { + GetData()->g_flags[0][std::string(var)] -= value[0]; + } + else if (*modifier == 1) { + GetData()->g_flags[0][std::string(var)] += value[0]; + } +} diff --git a/vndc/src/op_if.cpp b/vndc/src/op_if.cpp new file mode 100644 index 0000000..e733ca2 --- /dev/null +++ b/vndc/src/op_if.cpp @@ -0,0 +1,59 @@ +#include "Zero.hpp" + +#include "Funcs.hpp" + +/* + * Implements if vnds function. + * if var op val + * op is a c-style compare + * ('<=':0 '<':1 '==':2 '!=':3 '>': '>=':5) + */ + +void op_if(char* var, int* op, int* val) { + if (GetData()->if_fail) + return; + + int var_val = GetData()->s_flags[0][std::string(var)]; + + //printf("op_if(%s, %d, %d)\n", var, op[0], val[0]); + //printf("GetData()->s_flags[0][%s] = %d\n", var, GetData()->s_flags[0][std::string(var)]); + + switch (op[0]) { + case 0: + if ( !(var_val <= val[0]) ) + GetData()->if_fail = true; + else + GetData()->if_fail = false; + break; + case 1: + if ( !(var_val < val[0]) ) + GetData()->if_fail = true; + else + GetData()->if_fail = false; + break; + case 2: + if ( !(var_val == val[0]) ) + GetData()->if_fail = true; + else + GetData()->if_fail = false; + break; + case 3: + if ( !(var_val != val[0]) ) + GetData()->if_fail = true; + else + GetData()->if_fail = false; + break; + case 4: + if ( !(var_val > val[0]) ) + GetData()->if_fail = true; + else + GetData()->if_fail = false; + break; + case 5: + if ( !(var_val >= val[0]) ) + GetData()->if_fail = true; + else + GetData()->if_fail = false; + break; + } +} diff --git a/vndc/src/op_jump.cpp b/vndc/src/op_jump.cpp new file mode 100644 index 0000000..98395ba --- /dev/null +++ b/vndc/src/op_jump.cpp @@ -0,0 +1,47 @@ +#include "Zero.hpp" + +#include "Funcs.hpp" + +/* + * Implements jump vnds function. + * jump file + * The parser actually does most of the work. This + * just kind of gives it a nudge ans says 'reload k' + */ + +void op_jump(char* file, int* lineTo, bool isSave) { + if (GetData()->if_fail) + return; + memset(GetData()->current_scr, 0, 400); + if(!isSave) + snprintf(GetData()->current_scr, 400, "script/%s", file); + else + snprintf(GetData()->current_scr, 400, "%s", file); + + if(GetData()->debug_mode) { + memset(&GetData()->window_name[16], 0, sizeof(char)*400); + snprintf(&GetData()->window_name[16], 400-16-3, " (%s)", file); + GetData()->ctx->SetTitle(GetData()->window_name); + } + + if(GetData()->accessScriptHandle != NULL) + fclose(GetData()->accessScriptHandle); + + GetData()->accessScriptHandle = fopen(GetData()->current_scr, "r"); + if(GetData()->accessScriptHandle == NULL) { + printf("[error] Failed to open script file %s.\n", GetData()->current_scr); + } + + + if(lineTo != NULL) { + GetData()->currentLine = lineTo[0]; + char *line = (char*)calloc(sizeof(char), 400); + + while(--lineTo[0] > 0) { + fgets(line, 400, GetData()->accessScriptHandle); + } + } + else { + GetData()->currentLine = 0; + } +} diff --git a/vndc/src/op_music.cpp b/vndc/src/op_music.cpp new file mode 100644 index 0000000..a817896 --- /dev/null +++ b/vndc/src/op_music.cpp @@ -0,0 +1,30 @@ +#include "Zero.hpp" + +#include "Funcs.hpp" + +/* + * Implements music vnds function. + * music file + */ + +void op_music(char* file) { + if (GetData()->if_fail || GetData()->ctx->GetQuit()) + return; + + memset(GetData()->current_music, 0, 400); + + snprintf(GetData()->current_music, 400, "sound/%s", file); + + // Halt command + if (!strcmp(file, "~")) { + GetData()->ctx->Audio()->FlushMusic(); + } + // Play command + else { + GetData()->ctx->Audio()->FlushMusic(); + + int index = GetData()->ctx->Audio()->LoadMusic(GetData()->current_music); + + GetData()->ctx->Audio()->PlayMusicLoop(index); + } +} diff --git a/vndc/src/op_random.cpp b/vndc/src/op_random.cpp new file mode 100644 index 0000000..1607378 --- /dev/null +++ b/vndc/src/op_random.cpp @@ -0,0 +1,21 @@ +#include "Zero.hpp" + +#include "Funcs.hpp" + +/* + * Implements random vnds function. + * random var low high + */ + +bool seeded = false; + +void op_random(char* var, int* low, int* high) { + if (GetData()->if_fail) + return; + if (seeded == false) + srand(time(NULL)); + + int num = *low + ( rand() % ( *high - *low ) ); + + GetData()->s_flags[0][std::string(var)] = num; +} diff --git a/vndc/src/op_setimg.cpp b/vndc/src/op_setimg.cpp new file mode 100644 index 0000000..e2c9a21 --- /dev/null +++ b/vndc/src/op_setimg.cpp @@ -0,0 +1,30 @@ +#include "Zero.hpp" + +#include "Funcs.hpp" + +/* + * Implements setimg vnds function. + * bgload file x y + */ + +void op_setimg(char* file, int* x, int* y) { + if (GetData()->if_fail || GetData()->ctx->GetQuit()) + return; + + // Fadeout not implemented yet. + + char path[400]; + memset(path, 0, 400); + + snprintf(path, 400, "foreground/%s", file); + + // Load displayable. + UDisplayable* fg_add = new UDisplayable(GetData()->ctx, Normal, path); + + fg_add->SetXY(*x, *y); + + fg_add->Blit(); + + // Delete fg_new. We're done with it. + delete fg_add; +} diff --git a/vndc/src/op_setvar.cpp b/vndc/src/op_setvar.cpp new file mode 100644 index 0000000..b6477a9 --- /dev/null +++ b/vndc/src/op_setvar.cpp @@ -0,0 +1,37 @@ +#include "Zero.hpp" + +#include "Funcs.hpp" + +/* + * Implements gsetvar vnds function. + * gsetvar var mod val + * Modifier is '=' '+' or '-' in script, simplify to ('-':-1, '=':0, '+':1). + * MAY need to be UTF8 friendly + */ + +void op_setvar(char* var, int* modifier, int* value) { + if (GetData()->if_fail) + return; + + if(*modifier == 0) { + GetData()->s_flags[0][std::string(var)] = value[0]; + } + else if (*modifier == -1) { + GetData()->s_flags[0][std::string(var)] -= value[0]; + } + else if (*modifier == 1) { + GetData()->s_flags[0][std::string(var)] += value[0]; + } + else if (*modifier == -2) { + // There's a rare case on program start where a resetall + // happens. + + if(!strcmp(var, "~")) { + // We'll handle it by doing a delete & new on s_local + GetData()->s_flags[0].clear(); + return; + } + + GetData()->s_flags[0][std::string(var)] = 0; + } +} diff --git a/vndc/src/op_sound.cpp b/vndc/src/op_sound.cpp new file mode 100644 index 0000000..ec721cc --- /dev/null +++ b/vndc/src/op_sound.cpp @@ -0,0 +1,44 @@ +#include "Zero.hpp" + +#include "Funcs.hpp" + +/* + * Implements sound vnds function. + * sound file [times] + */ + +void op_sound(char* file, int* times) { + if (GetData()->if_fail || GetData()->ctx->GetQuit()) + return; + + // Fadeout not implemented yet. + + // Halt command + if (!strcmp(file, "~")) { + GetData()->ctx->Audio()->FlushSfx(); + return; + } + // Play command + else { + int count = 1; + if (times != NULL) + count = *times; + + char path[400]; + memset(path, 0, 400); + + snprintf(path, 400, "sound/%s", file); + + //printf("[op_sound] path: '%s'\n", path); + + // Load displayable. + int sfxi = GetData()->ctx->Audio()->LoadSfx(path); + + if (count == -1) { + GetData()->ctx->Audio()->PlaySfx(sfxi, count); + } + else { + GetData()->ctx->Audio()->PlaySfx(sfxi, count-1); + } + } +} diff --git a/vndc/src/op_text.cpp b/vndc/src/op_text.cpp new file mode 100644 index 0000000..02a18d6 --- /dev/null +++ b/vndc/src/op_text.cpp @@ -0,0 +1,119 @@ +#include "Zero.hpp" + +#include "Funcs.hpp" + +/* + * Implements text vnds function. + * text string + */ + +void op_text(char* string) { + if (GetData()->if_fail || GetData()->ctx->GetQuit()) + return; + + // Search thru for vars and rebuild string. + + // Linebreak on zero-length, and render size exceed. + if (GetData()->text_y > (GetData()->render_y2) || strlen(string) < 1) + op_cleartext(); + + if(strlen(string) < 1) + return; + + // Improvised linebreak. Also, an extension. + if(GetData()->vndc_enabled && string[1] == '-' && string[2] == '-' && string[3] == '-') { + op_cleartext(); + } + // Improvised voice detect. Extension. + // This is based on toggling. + // If the quote is incomplete, it will be stopped on end. + // If not, it will continue voice until the next quoted line. + if(GetData()->vndc_enabled) { + GetData()->is_spoken_line = false; + + int quotes = 0; + for(int i=0; i < (int)strlen(string); i++) { + if(string[i] == '"') quotes++; + } + if(quotes > 0) GetData()->is_spoken_line = true; + } + // Wait for input, then blank + if(!strcmp(string, "!")) { + GetData()->wait_input = true; + Wait(); + op_cleartext(); + } + // Blank screen + else if(!strcmp(string, "~")) { + op_cleartext(); + } + // Output + else { + bool noclick = false; + // No click required + if(string[0] == '@') { + noclick = true; + string = &string[1]; + } + + + TextManager* txt = GetData()->ctx->Text(); + + if(txt->TestLen(string) > (GetData()->render_x2 - GetData()->render_x1)) { + + /* new algo */ + char** ptrs = NULL; + int lines = 0; + + int len = strlen(string); + + int counted = 0; + + while(counted < len) { + char* pt_start = &string[counted]; + char* pt_end = &pt_start[strlen(pt_start)]; + + while(pt_end > pt_start && txt->TestLen(pt_start) > (GetData()->render_x2 - GetData()->render_x1)) { + *pt_end = ' '; + --pt_end; + + while (*pt_end != ' ' && pt_end > pt_start) --pt_end; + + *pt_end = '\0'; + } + + #ifdef DEBUG_OVERKILL + printf("Reduced line %d: %s\n", lines, pt_start); + #endif + + ptrs = (char**)realloc(ptrs, sizeof(char*)*(lines+1)); + + ptrs[lines] = pt_start; + + counted += strlen(pt_start) + 1; + + ++lines; + } + + if( ( lines * 35 + GetData()->text_y ) > GetData()->render_y2 ) + op_cleartext(); + + for(int i=0; i < lines; i++) { + //printf("[br] %s\n", ptrs[i]); + txt->Render(ptrs[i], GetData()->text_x, GetData()->text_y); + GetData()->text_y += 35; + } + + free(ptrs); + + } + else { + txt->Render(string, GetData()->text_x, GetData()->text_y); + GetData()->text_y += 35; + } + + if(!noclick) { + GetData()->wait_input = true; + } + } +} -- 2.39.5