From 121934c454fb2b2f144e7c0274e2f0c8b9ebe8ee Mon Sep 17 00:00:00 2001 From: Ian Burgmyer Date: Thu, 25 Apr 2019 06:50:50 -0400 Subject: [PATCH] Initial commit. * 256 color palette viewer. * usage: ./palview * If vgamode is omitted or 0, it displays the palette as-is. * If vgamode is 1, it multiplies all palette values by 4. --- .gitignore | 86 +++++++++++++ .idea/encodings.xml | 4 + .idea/inspectionProfiles/Project_Default.xml | 10 ++ .idea/misc.xml | 15 +++ .idea/modules.xml | 8 ++ .idea/palview.iml | 2 + CMakeLists.txt | 16 +++ LICENSE | 24 ++++ Makefile | 44 +++++++ README.md | 186 +++++++++++++++++++++++++++ src/defs.h | 19 +++ src/event.c | 68 ++++++++++ src/event.h | 15 +++ src/game.c | 101 +++++++++++++++ src/game.h | 10 ++ src/log.c | 52 ++++++++ src/log.h | 16 +++ src/main.c | 31 +++++ src/video.c | 80 ++++++++++++ src/video.h | 19 +++ sublime/sdl2-sandbox.sublime-project | 23 ++++ 21 files changed, 829 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/encodings.xml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/palview.iml create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 src/defs.h create mode 100644 src/event.c create mode 100644 src/event.h create mode 100644 src/game.c create mode 100644 src/game.h create mode 100644 src/log.c create mode 100644 src/log.h create mode 100644 src/main.c create mode 100644 src/video.c create mode 100644 src/video.h create mode 100644 sublime/sdl2-sandbox.sublime-project diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..529a123 --- /dev/null +++ b/.gitignore @@ -0,0 +1,86 @@ +# Created by https://www.gitignore.io/api/clion +# Edit at https://www.gitignore.io/?templates=clion + +### CLion ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### CLion Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +.idea/sonarlint + +# End of https://www.gitignore.io/api/clion + +# StarLight stuff! +src/version.h diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..15a15b2 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..146ab09 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..6b465b5 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..77e9a2b --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/palview.iml b/.idea/palview.iml new file mode 100644 index 0000000..f08604b --- /dev/null +++ b/.idea/palview.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..6057363 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.13) +project(palview C) + +set(CMAKE_C_STANDARD 90) + +find_package(SDL2 REQUIRED) +include_directories(${SDL2_INCLUDE_DIRS}) + +add_executable(palview + src/main.c + src/event.c + src/game.c + src/log.c + src/video.c) + +target_link_libraries(palview ${SDL2_LIBRARIES}) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..cf1ab25 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0c4a002 --- /dev/null +++ b/Makefile @@ -0,0 +1,44 @@ +# A Generic Makefile For Quick and Dirty Projects +# +# This Makefile has been tested using GNU make and bash. Your mileage may vary +# with other make implementations and/or shells. + +CFLAGS = $(shell sdl2-config --cflags) +LDFLAGS = $(shell sdl2-config --libs) + +CC = cc +MKDIR = mkdir -p + +OBJDIR = ./obj +BINDIR = ./bin +ASSETDIR = ./assets + +# System-specific Makefile overrides. +-include Makefile.override + +# The rest of these settings should are automatically configured. Tweak at your +# own peril! :P +OUTFILE = $(shell basename $(shell pwd)) +ALL_C := $(shell find . -type f -name '*.c') +OBJFILES := $(addprefix $(OBJDIR)/,$(ALL_C:%.c=%.o)) + +all: $(OUTFILE) + +$(OBJDIR)/%.o: %.c + $(MKDIR) $(@D) + $(CC) $(CFLAGS) -o $@ -c $< + +$(OUTFILE): $(OBJFILES) + $(MKDIR) $(BINDIR) + $(CC) $(LDFLAGS) -o $(BINDIR)/$(OUTFILE) $^ + + if [ -d $(ASSETDIR) ]; then \ + cp $(ASSETDIR)/* $(BINDIR); \ + fi + +test: $(OUTFILE) + cd $(BINDIR);./$(OUTFILE) + +clean: + $(RM) -r $(OBJFILES) + $(RM) $(BINDIR)/$(OUTFILE) diff --git a/README.md b/README.md new file mode 100644 index 0000000..98c7115 --- /dev/null +++ b/README.md @@ -0,0 +1,186 @@ +# SDL2 Sandbox + +## Introduction + +I've made quite a few little experimental projects in SDL. As such, I've +written very similar initialization code multiple times. I decided that it +would be much easier to put some quick boilerplate code together to give me a +base to quickly experiment with new ideas without having to keep reinventing +the wheel. + +## Requirements + +This project is aimed at people who are programming using a Linux system. A +compiler toolchain, such as gcc with binutils, and an implementation of Make +are required to build the project. Please note that the Make implementation +must support the $(shell) syntax. + +If you're running a Linux system with the development tools installed, odds are +this will work without a hitch. If you're using *BSD, you may have to use GNU +make (gmake) for this to build properly. + +macOS and Windows users will have to do a bit more work to get this running, +whether it be creating an Xcode/MSVC project, manually compiling SDL, or using +a third-party package manager and/or toolchain (such as mingw64 on Windows or +homebrew on macOS). + +SDL 2.0 is required. Later versions may work, but earlier versions will not. + +## What's Included? + +This project includes a Makefile, a working sample project, and ignore files +for git and Mercurial. It's designed so that you can compile it, watch it work, +then immediately start making changes. + +## How to Use This Project + +The first step to using this project is to determine which branch suits your +skill level. The `master` branch--the default--is very heavily commented, +intended to help ease beginners into C and SDL2. All major calls and actions +are commented, and the rationale behind each step is explained in as much +detail as is feasible. + +The `terse` branch is much cleaner, intended for people who just want to be +able to use this as a base to build other projects. + +Since this is intended to be used as a base, it is highly recommended that you +create your own repository (if you choose to use one) rather than keeping the +existing one. For example, if you wanted to create a project called "my_game", +run the following from your terminal emulator of choice: + +``` +git clone https://github.com/Spectere/sdl2_sandbox.git my_game +cd my_game +rm -rf .git +git init +``` + +The above command clones the git repository, changes into the project +directory, removes the existing git repository, then creates a new one in its +place. If you prefer to use Mercurial, use `hg init` in place of +`git init`. + +If you are using a repository, be sure to delete the ignore file that does +not apply to your VCS of choice. For example, if you're using git, you should +run `rm .hgignore`, while if you're using Mercurial you should run +`rm .gitignore`. If you don't want to use either, both files can be removed. + +After your project directory is prepared, type `make` to build the project. +If there are no errors, type `make test` to launch it. You should see a window +pop up with some color shifting. Either press ESC or close the window to exit. + +Now, modify `defs.h` to customize the window title text and resolution. The +application loop is contained in `game.c`, and input handling is done in +`event.c`. Happy coding! + +## Caveats + +While this project does provide a quick and easy way to create an SDL2 project, +it was not intended for large-scale or release-ready projects. Here are a few +potential issues that you can run into. + +* The logger is simple, both in ease-of-use and functionality. It will not +support all platforms flawlessly. + +* The video settings are hardcoded in `defs.h`. + +* No provisions have been made for audio input and output, network support, +or other features. The only things that have been accounted for are video +and basic input. + +* Game logic is tied to the framerate, and vsync is leveraged to limit the +framerate. This project does not contain any timing routines. + +* The Makefile was written to include all C files in the src/ directory, +and also names the executable after the directory that contains the +project. Additionally, no automatic configuration is supported, and +cross-platform support is not guaranteed. + +* This has not been tested with C++ projects. + +## Contributing + +If you can think of any ways to improve this project, feel free to submit a +pull request. Please note that PRs that push the project too far past its main +goals will most likely be rejected. The goals are as follows: + +1. To provide a base for experimentation and prototyping. +2. To provide beginners with a means of easing into SDL2 programming. + +It's recommended that contributions provide thorough documentation, as seen in +the master branch, but this is not required. + +Also, please take note of the following style guidelines in this section: + +### Comments + +All source code comments should be C89-style (using `/*` and `*/`), not +C++-style (using `//`). Comments should be made above the applicable line, +though inline comments may be used where appropriate. + +A brief description of the file should be included on every source and header +file. + +Comments should not exceed 80 columns of width, including whitespace. + +### Braces + +Open braces should appear at the end of all block statements, including +function definitions. + +### Whitespace and Code Width + +Code should be indented using tabs. Total width should be counted counted as if +each tab were 4 spaces in width, as that is the default with most modern +graphical IDEs. + +Parenthesis should be placed against control statements, function calls, and +function declarations, with no extra spaces. When pointers are declared, be it +in function or variable definitions, the asterisk should be placed against the +name of the pointer. + +80 columns of width should be considered a soft cap, as that will allow easy +code examination when using multiple editor panes and a terminal. 120 columns +should be considered a hard cap. Where feasible, a single parameter or equation +should not be broken across multiple lines. + +If a function call must span multiple lines, the subsequent lines should be +indented with a single tab. + +If a function definition must span multiple lines, the subsequent lines should +be aligned with spaces to one character after the open parenthesis. + +If a control statement must span multiple lines, the subsequent lines should be +indented with two tabs. That said, this probably should never occur on a +project with this scope. + +### Include Guards + +`#ifndef/#define/#endif` should be used for all include guards. At this time, +`#pragma once` should be avoided. The definition format that should be used is +the include filename, in all caps, with underscores surrounding it and +replacing dots. The `#endif` must have the definition stated in an inline +comment. + +For example, if you're working on a header file called `foo.h`, it should look +like the following: + +```c +/* foo.h + * + * Exposes public functions related to the foo subsystem. + */ + +#ifndef _FOO_H_ +#define _FOO_H_ + +void foo_bar(); + +#endif /* _FOO_H_ */ +``` + +## Licensing + +This project is released under the Unlicense, effectively putting it into the +public domain. Feel free to use, modify, and even relicense it to best suit +your needs. No attribution is required. diff --git a/src/defs.h b/src/defs.h new file mode 100644 index 0000000..dda0c0e --- /dev/null +++ b/src/defs.h @@ -0,0 +1,19 @@ +/* defs.h - Global definitions and constants. */ + +/* The default caption of the SDL2 window. */ +#define PROJECT_NAME "SDL2 Sandbox" + +/* The size of the pixmap. */ +#define RENDER_WIDTH 322 +#define RENDER_HEIGHT 322 + +/* The SDL window size. */ +#define WINDOW_WIDTH 966 +#define WINDOW_HEIGHT 966 + +/* Maximum length of the log format screen, including the severity tag. */ +#define LOG_LEN 160 + +/* How the color box things get displayed. */ +#define BOX_SIZE 20 +#define BOX_SPACING 2 diff --git a/src/event.c b/src/event.c new file mode 100644 index 0000000..4d9ee0c --- /dev/null +++ b/src/event.c @@ -0,0 +1,68 @@ +/* event.c - Event handler functions. */ + +#include + +#include "event.h" + +event_result_t event_keyboard(const SDL_Event e) { + SDL_KeyboardEvent kb = e.key; + + if(kb.type == SDL_KEYUP) { + switch(kb.keysym.sym) { + case SDLK_ESCAPE: + return EV_QUIT; + } + } + + return EV_NONE; +} + +event_result_t event_mouse_button(const SDL_Event e) { + SDL_MouseButtonEvent btn = e.button; + return EV_NONE; +} + +event_result_t event_mouse_wheel(const SDL_Event e) { + SDL_MouseWheelEvent wheel = e.wheel; + return EV_NONE; +} + +event_result_t event_mouse_motion(const SDL_Event e) { + SDL_MouseMotionEvent motion = e.motion; + return EV_NONE; +} + +event_result_t event_window(const SDL_Event e) { + SDL_WindowEvent wnd = e.window; + return EV_NONE; +} + +/* Main event processor. */ +event_result_t event_process() { + SDL_Event e; + SDL_PollEvent(&e); + + switch(e.type) { + case SDL_KEYDOWN: + case SDL_KEYUP: + return event_keyboard(e); + + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + return event_mouse_button(e); + + case SDL_MOUSEWHEEL: + return event_mouse_wheel(e); + + case SDL_MOUSEMOTION: + return event_mouse_motion(e); + + case SDL_WINDOWEVENT: + return event_window(e); + + case SDL_QUIT: + return EV_QUIT; + } + + return EV_NONE; +} diff --git a/src/event.h b/src/event.h new file mode 100644 index 0000000..dd488ae --- /dev/null +++ b/src/event.h @@ -0,0 +1,15 @@ +/* event.h - Event handler functions. */ + +#ifndef _EVENT_H_ +#define _EVENT_H_ + +/* Values that can be sent to the main game loop. */ +typedef enum { + EV_NONE, + EV_QUIT +} event_result_t; + +/* Main event processor. */ +event_result_t event_process(); + +#endif /* _EVENT_H_ */ diff --git a/src/game.c b/src/game.c new file mode 100644 index 0000000..ccbe8fe --- /dev/null +++ b/src/game.c @@ -0,0 +1,101 @@ +/* game.c - Main game loop. */ + +#include +#include +#include +#include +#include +#include +#include + +#include "defs.h" +#include "event.h" +#include "video.h" + +Uint32 palette[256]; + +void load_palette(char* palfile, SDL_bool vga) { + struct stat st; + FILE *f; + int i; + + stat(palfile, &st); + if(errno) { + printf("unable to stat file: %s\n", strerror(errno)); + exit(1); + } + + if(st.st_size != 768) { + printf("invalid size (expected 768 byes, got %li bytes)\n", st.st_size); + exit(1); + } + + f = fopen(palfile, "rb"); + if(f == NULL) { + printf("unable to open file: %s\n", strerror(errno)); + exit(1); + } + + for(i = 0; i < 256; i++) { + Uint8 r, g, b; + + r = (Uint8)fgetc(f); + g = (Uint8)fgetc(f); + b = (Uint8)fgetc(f); + + if(!vga) + palette[i] = RGB(r, g, b); + else + palette[i] = RGB(r * 4, g * 4, b * 4); + } + + fclose(f); +} + +void game_loop(char *palfile, SDL_bool vga) { + event_result_t ev = EV_NONE; + SDL_bool running = SDL_TRUE; + int cx, cy; + + load_palette(palfile, vga); + + if(video_init(PROJECT_NAME, RENDER_WIDTH, RENDER_HEIGHT, WINDOW_WIDTH, + WINDOW_HEIGHT) != 0) { + printf("error initializing video\n"); + exit(1); + } + + /* Clear the framebuffer. */ + memset(pixels, 0x00, RENDER_WIDTH * RENDER_HEIGHT * 4); + + /* Plot things! */ + for(cy = 0; cy < 16; cy++) { + for(cx = 0; cx < 16; cx++) { + int i = (cy * 16) + cx; + int c = palette[i]; + + int sx, sy; + for(sy = BOX_SPACING; sy < BOX_SIZE; sy++) { + for(sx = BOX_SPACING; sx < BOX_SIZE; sx++) { + int x = (BOX_SIZE) * cx + sx; + int y = (BOX_SIZE) * cy + sy; + + pixels[POS(x, y)] = c; + } + } + } + + } + + while(running) { + ev = event_process(); + + switch(ev) { + case EV_QUIT: + running = SDL_FALSE; + break; + } + + video_update(); + } +} diff --git a/src/game.h b/src/game.h new file mode 100644 index 0000000..4859411 --- /dev/null +++ b/src/game.h @@ -0,0 +1,10 @@ +/* game.h - Main game loop. */ + +#ifndef _GAME_H_ +#define _GAME_H_ + +#include + +void game_loop(char* palfile, SDL_bool vga); + +#endif /* _GAME_H_ */ diff --git a/src/log.c b/src/log.c new file mode 100644 index 0000000..ea7d8d6 --- /dev/null +++ b/src/log.c @@ -0,0 +1,52 @@ +/* log.c - Application logging functionality. */ + +#include +#include +#include + +#include "defs.h" +#include "log.h" + +void lprint(log_level_t level, const char *format, ...) { + char output_format[LOG_LEN]; + + va_list args; + va_start(args, format); + + if(strlen(format) + 10 > LOG_LEN) { + fprintf(stderr, "[!!!] Log string is too long!\n"); + vfprintf(stdout, format, args); + fprintf(stdout, "\n"); + va_end(args); + return; + } + + switch(level) { + case DEBUG: + strcpy(output_format, "[DEBUG] "); + break; + case INFO: + strcpy(output_format, "[INFO] "); + break; + case WARN: + strcpy(output_format, "[WARN] "); + break; + case ERROR: + strcpy(output_format, "[ERROR] "); + break; + default: + /* If no valid severity was passed, initialize the string. */ + strcpy(output_format, ""); + break; + } + + strcat(output_format, format); + strcat(output_format, "\n"); + + if(level == ERROR) + vfprintf(stderr, output_format, args); + else + vfprintf(stdout, output_format, args); + + va_end(args); +} diff --git a/src/log.h b/src/log.h new file mode 100644 index 0000000..b2dcdd5 --- /dev/null +++ b/src/log.h @@ -0,0 +1,16 @@ +/* log.h - Application logging functionality. */ + +#ifndef _LOG_H_ +#define _LOG_H_ + +/* Severity levels used by lprint(). */ +typedef enum { + DEBUG, + INFO, + WARN, + ERROR +} log_level_t; + +void lprint(log_level_t level, const char *format, ...); + +#endif /* _LOG_H_ */ diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..a155567 --- /dev/null +++ b/src/main.c @@ -0,0 +1,31 @@ +/* main.c - Program entry point. */ + +#include + +#include "defs.h" +#include "game.h" +#include "video.h" + +int main(int argc, char **argv) { + SDL_bool vga = SDL_FALSE; + + if(argc < 2) { + printf("\n usage: palview (palette file) [vga]\n\n"); + printf(" vga should be 1 if the palette is a VGA palette (color range: 0x00-0x3F,\n"); + printf(" otherwise it should be 0. If not specified, it will default to 0.\n\n"); + return 1; + } + + if(argc > 2) { + printf("vga: %s\n", argv[2]); + if(strncmp(argv[2], "1", 1) == 0) + vga = SDL_TRUE; + } + + game_loop(argv[1], vga); + + video_close(); + SDL_Quit(); + + return 0; +} diff --git a/src/video.c b/src/video.c new file mode 100644 index 0000000..d2b60dd --- /dev/null +++ b/src/video.c @@ -0,0 +1,80 @@ +/* video.c - Initializes and updates the window. */ + +#include + +#include "log.h" +#include "video.h" + +int tex_width, tex_height, wnd_width, wnd_height; + +Uint32 *pixels; + +SDL_Window *window = NULL; +SDL_Renderer *renderer = NULL; +SDL_Texture *texture = NULL; + +void video_close() { + lprint(INFO, "Closing video subsystem"); + + SDL_DestroyTexture(texture); + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + + SDL_QuitSubSystem(SDL_INIT_VIDEO); +} + +int video_init(const char *title, int render_width, int render_height, + int window_width, int window_height) { + tex_width = render_width; + tex_height = render_height; + wnd_width = window_width; + wnd_height = window_height; + + SDL_Init(SDL_INIT_VIDEO); + + lprint(INFO, "Initializing video (%ix%i surface, %ix%i window)...", + tex_width, tex_height, wnd_width, wnd_height); + + /* Create an SDL window. */ + lprint(DEBUG, "Creating window"); + window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, window_width, window_height, 0); + if(window == NULL) { + lprint(ERROR, "Error creating window: %s", SDL_GetError()); + return 1; + } + + /* Create the renderer. */ + lprint(DEBUG, "Creating hardware accelerated renderer"); + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + if(renderer == NULL) { + /* Attempt to fall back to software rendering. */ + lprint(WARN, "Failed to create hardware accelerated renderer: %s", SDL_GetError()); + lprint(WARN, "Attempting to create a software renderer"); + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_SOFTWARE | SDL_RENDERER_PRESENTVSYNC); + if(renderer == NULL) { + lprint(ERROR, "Error creating renderer: %s", SDL_GetError()); + return 1; + } + } + + /* Create an ARGB8888 texture. */ + lprint(DEBUG, "Creating texture"); + texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_STREAMING, tex_width, tex_height); + if(texture == NULL) { + lprint(ERROR, "Error creating texture: %s", SDL_GetError()); + return 1; + } + + pixels = malloc(sizeof(Uint32) * tex_width * tex_height); + + lprint(INFO, "Video subsystem initialized successfully"); + return 0; +} + +void video_update() { + SDL_UpdateTexture(texture, NULL, pixels, tex_width * sizeof(Uint32)); + SDL_RenderCopy(renderer, texture, NULL, NULL); + SDL_RenderPresent(renderer); +} diff --git a/src/video.h b/src/video.h new file mode 100644 index 0000000..2b1f999 --- /dev/null +++ b/src/video.h @@ -0,0 +1,19 @@ +/* video.h - Initializes and updates the window. */ + +#ifndef _VIDEO_H_ +#define _VIDEO_H_ + +#include +#include "defs.h" + +#define RGB(r, g, b) (0xFF000000 | (r << 16) | (g << 8) | b) +#define POS(x, y) ((RENDER_WIDTH * y) + x) + +extern Uint32 *pixels; + +void video_close(); +int video_init(const char *title, int render_width, int render_height, + int window_width, int window_height); +void video_update(); + +#endif /* _VIDEO_H_ */ diff --git a/sublime/sdl2-sandbox.sublime-project b/sublime/sdl2-sandbox.sublime-project new file mode 100644 index 0000000..baf6731 --- /dev/null +++ b/sublime/sdl2-sandbox.sublime-project @@ -0,0 +1,23 @@ +{ + "folders": + [ + { + "name": "Project Files", + "path": "..", + "file_include_patterns": [ + "Makefile", + "LICENSE", + "README.md", + ".gitignore", + ".hgignore" + ], + "folder_exclude_patterns": [ + "*" + ] + }, + { + "name": "Source", + "path": "../src" + } + ] +}