diff --git a/examples/sdl-renderer.c b/examples/sdl-renderer.c new file mode 100644 index 0000000..bd42334 --- /dev/null +++ b/examples/sdl-renderer.c @@ -0,0 +1,153 @@ +// MIT License + +// Copyright (c) 2017 Vadim Grigoruk @nesbox + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// 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 OR COPYRIGHT HOLDERS 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. + +#include +#include +#include + +int main(int argc, char **argv) +{ + FILE* file = fopen("cart.tic", "rb"); + + if(file) + { + fseek(file, 0, SEEK_END); + int size = ftell(file); + fseek(file, 0, SEEK_SET); + + void* cart = SDL_malloc(size); + if(cart) fread(cart, size, 1, file); + fclose(file); + + if(cart) + { + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO); + + bool quit = false; + + { + SDL_Window* window = SDL_CreateWindow("TIC-80 SDL demo", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, TIC80_WIDTH, TIC80_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); + SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, TIC80_WIDTH, TIC80_HEIGHT); + + SDL_AudioDeviceID audioDevice = 0; + SDL_AudioSpec audioSpec; + bool audioStarted = false; + + { + SDL_AudioSpec want = + { + .freq = 44100, + .format = AUDIO_S16, + .channels = 1, + .userdata = NULL, + }; + + audioDevice = SDL_OpenAudioDevice(NULL, 0, &want, &audioSpec, SDL_AUDIO_ALLOW_ANY_CHANGE); + } + + tic80_input input = {.first.data = 0, .second.data = 0}; + + tic80* tic = tic80_create(audioSpec.freq); + tic80_load(tic, cart, size); + + if(tic) + { + while(!quit) + { + SDL_Event event; + + while(SDL_PollEvent(&event)) + { + switch(event.type) + { + case SDL_QUIT: + quit = true; + break; + } + } + + { + input.first.data = input.second.data = 0; + const uint8_t* keyboard = SDL_GetKeyboardState(NULL); + + static const SDL_Scancode Keys[] = + { + SDL_SCANCODE_UP, + SDL_SCANCODE_DOWN, + SDL_SCANCODE_LEFT, + SDL_SCANCODE_RIGHT, + + SDL_SCANCODE_Z, + SDL_SCANCODE_X, + SDL_SCANCODE_A, + SDL_SCANCODE_S, + }; + + for (int i = 0; i < SDL_arraysize(Keys); i++) + { + if (keyboard[Keys[i]]) + { + input.first.data |= (1 << i); + } + } + } + + tic80_tick(tic, input); + + if (!audioStarted && audioDevice) + { + audioStarted = true; + SDL_PauseAudioDevice(audioDevice, 0); + } + + SDL_QueueAudio(audioDevice, tic->sound.buffer, tic->sound.size); + + SDL_RenderClear(renderer); + + { + void* pixels = NULL; + int pitch = 0; + SDL_LockTexture(texture, NULL, &pixels, &pitch); + SDL_memcpy(pixels, tic->screen.buffer, tic->screen.size); + SDL_UnlockTexture(texture); + SDL_RenderCopy(renderer, texture, NULL, NULL); + } + + SDL_RenderPresent(renderer); + } + + tic80_delete(tic); + } + + SDL_DestroyTexture(texture); + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_CloseAudioDevice(audioDevice); + } + + SDL_free(cart); + } + } + + return 0; +} diff --git a/include/tic80/tic80.h b/include/tic80/tic80.h new file mode 100644 index 0000000..8118367 --- /dev/null +++ b/include/tic80/tic80.h @@ -0,0 +1,91 @@ +// MIT License + +// Copyright (c) 2017 Vadim Grigoruk @nesbox + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// 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 OR COPYRIGHT HOLDERS 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. + +#pragma once + +#include "tic80_config.h" +#include "tic80_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define TIC80_WIDTH 240 +#define TIC80_HEIGHT 136 + +typedef struct +{ + struct + { + s16* buffer; + s32 size; + } sound; + + struct + { + void* buffer; + s32 size; + } screen; +} tic80; + +typedef union +{ + struct + { + bool up:1; + bool down:1; + bool left:1; + bool right:1; + bool a:1; + bool b:1; + bool x:1; + bool y:1; + }; + + u8 data; +} tic80_gamepad; + +typedef union +{ + struct + { + tic80_gamepad first; + tic80_gamepad second; + }; + + struct + { + u16 mouse:15; + u16 pressed:1; + }; + + u16 data; +} tic80_input; + +TIC80_API tic80* tic80_create(s32 samplerate); +TIC80_API void tic80_load(tic80* tic, void* cart, s32 size); +TIC80_API void tic80_tick(tic80* tic, tic80_input input); +TIC80_API void tic80_delete(tic80* tic); + +#ifdef __cplusplus +} +#endif diff --git a/include/tic80/tic80_config.h b/include/tic80/tic80_config.h new file mode 100644 index 0000000..7962c32 --- /dev/null +++ b/include/tic80/tic80_config.h @@ -0,0 +1,45 @@ +// MIT License + +// Copyright (c) 2017 Vadim Grigoruk @nesbox + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// 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 OR COPYRIGHT HOLDERS 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. + +#pragma once + +#if (defined(WIN32) || defined(_WIN32) || defined(__MINGW32__)) +# undef __WINDOWS__ +# define __WINDOWS__ 1 +#endif + +#if (defined(linux) || defined(__linux) || defined(__linux__)) +# undef __LINUX__ +# define __LINUX__ 1 +#endif + +#ifndef TIC80_API +# if defined(TIC80_SHARED) +# if defined(__WINDOWS__) +# define TIC80_API __declspec(dllexport) +# elif defined(__LINUX__) +# define TIC80_API __attribute__ ((visibility("default"))) +# endif +# else +# define TIC80_API +# endif +#endif \ No newline at end of file diff --git a/include/tic80/tic80_types.h b/include/tic80/tic80_types.h new file mode 100644 index 0000000..c24a77a --- /dev/null +++ b/include/tic80/tic80_types.h @@ -0,0 +1,36 @@ +// MIT License + +// Copyright (c) 2017 Vadim Grigoruk @nesbox + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// 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 OR COPYRIGHT HOLDERS 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. + +#pragma once + +#include +#include + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; diff --git a/lib/windows/tic80.dll b/lib/windows/tic80.dll new file mode 100644 index 0000000..244a83b Binary files /dev/null and b/lib/windows/tic80.dll differ diff --git a/lib/windows/tic80.lib b/lib/windows/tic80.lib new file mode 100644 index 0000000..3b71052 Binary files /dev/null and b/lib/windows/tic80.lib differ