Browse Source
* 256 color palette viewer. * usage: ./palview <palette> <vgamode> * If vgamode is omitted or 0, it displays the palette as-is. * If vgamode is 1, it multiplies all palette values by 4.master
Ian Burgmyer
5 years ago
commit
121934c454
21 changed files with 829 additions and 0 deletions
@ -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 |
@ -0,0 +1,4 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<project version="4"> |
||||||
|
<component name="Encoding" addBOMForNewFiles="with NO BOM" /> |
||||||
|
</project> |
@ -0,0 +1,10 @@ |
|||||||
|
<component name="InspectionProjectProfileManager"> |
||||||
|
<profile version="1.0"> |
||||||
|
<option name="myName" value="Project Default" /> |
||||||
|
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false"> |
||||||
|
<option name="processCode" value="true" /> |
||||||
|
<option name="processLiterals" value="true" /> |
||||||
|
<option name="processComments" value="true" /> |
||||||
|
</inspection_tool> |
||||||
|
</profile> |
||||||
|
</component> |
@ -0,0 +1,15 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<project version="4"> |
||||||
|
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" /> |
||||||
|
<component name="CidrRootsConfiguration"> |
||||||
|
<sourceRoots> |
||||||
|
<file path="$PROJECT_DIR$/src" /> |
||||||
|
</sourceRoots> |
||||||
|
</component> |
||||||
|
<component name="JavaScriptSettings"> |
||||||
|
<option name="languageLevel" value="ES6" /> |
||||||
|
</component> |
||||||
|
<component name="NodePackageJsonFileManager"> |
||||||
|
<packageJsonPaths /> |
||||||
|
</component> |
||||||
|
</project> |
@ -0,0 +1,8 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<project version="4"> |
||||||
|
<component name="ProjectModuleManager"> |
||||||
|
<modules> |
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/palview.iml" filepath="$PROJECT_DIR$/.idea/palview.iml" /> |
||||||
|
</modules> |
||||||
|
</component> |
||||||
|
</project> |
@ -0,0 +1,2 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<module classpath="CMake" type="CPP_MODULE" version="4" /> |
@ -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}) |
@ -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 <http://unlicense.org> |
@ -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)
|
@ -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. |
@ -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 |
@ -0,0 +1,68 @@ |
|||||||
|
/* event.c - Event handler functions. */ |
||||||
|
|
||||||
|
#include <SDL.h> |
||||||
|
|
||||||
|
#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; |
||||||
|
} |
@ -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_ */ |
@ -0,0 +1,101 @@ |
|||||||
|
/* game.c - Main game loop. */ |
||||||
|
|
||||||
|
#include <errno.h> |
||||||
|
#include <SDL.h> |
||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <sys/stat.h> |
||||||
|
#include <sys/types.h> |
||||||
|
#include <unistd.h> |
||||||
|
|
||||||
|
#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(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,10 @@ |
|||||||
|
/* game.h - Main game loop. */ |
||||||
|
|
||||||
|
#ifndef _GAME_H_ |
||||||
|
#define _GAME_H_ |
||||||
|
|
||||||
|
#include <SDL_types.h> |
||||||
|
|
||||||
|
void game_loop(char* palfile, SDL_bool vga); |
||||||
|
|
||||||
|
#endif /* _GAME_H_ */ |
@ -0,0 +1,52 @@ |
|||||||
|
/* log.c - Application logging functionality. */ |
||||||
|
|
||||||
|
#include <stdio.h> |
||||||
|
#include <stdarg.h> |
||||||
|
#include <string.h> |
||||||
|
|
||||||
|
#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); |
||||||
|
} |
@ -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_ */ |
@ -0,0 +1,31 @@ |
|||||||
|
/* main.c - Program entry point. */ |
||||||
|
|
||||||
|
#include <stdio.h> |
||||||
|
|
||||||
|
#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; |
||||||
|
} |
@ -0,0 +1,80 @@ |
|||||||
|
/* video.c - Initializes and updates the window. */ |
||||||
|
|
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
#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); |
||||||
|
} |
@ -0,0 +1,19 @@ |
|||||||
|
/* video.h - Initializes and updates the window. */ |
||||||
|
|
||||||
|
#ifndef _VIDEO_H_ |
||||||
|
#define _VIDEO_H_ |
||||||
|
|
||||||
|
#include <SDL.h> |
||||||
|
#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_ */ |
@ -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" |
||||||
|
} |
||||||
|
] |
||||||
|
} |
Loading…
Reference in new issue