xormod/xormod.c

220 lines
6.7 KiB
C

#include "font.h"
#include "EGA8x8.h"
#include "platform.h"
#include <stdio.h>
#include <SDL.h>
#define SWAP(a, b) ({ \
__typeof(a) tmp = (a); \
(a) = (b); \
(b) = tmp; \
})
typedef struct {
int x1;
int y1;
int x2;
int y2;
int w;
int h;
SDL_Surface *surface;
SDL_Texture *texture;
uint32_t *pixels;
uint32_t color;
} Picture;
static void Picture_render(Picture *p, SDL_Renderer *rend);
static Picture *Picture_new(SDL_Renderer *rend,
int x, int y, int w, int h, uint32_t color) {
Picture *p = calloc(1, sizeof(Picture));
p->x1 = x;
p->x2 = x + w;
p->y1 = y;
p->y2 = y + h;
p->w = w;
p->h = h;
p->color = color;
int stride = (w + 7) / 8 * 8;
p->pixels = malloc(stride * h * sizeof(uint32_t));
p->surface = SDL_CreateRGBSurfaceWithFormatFrom(
p->pixels, w, h, 32, stride * sizeof(uint32_t),
SDL_PIXELFORMAT_RGBA32);
Picture_render(p, rend);
return p;
}
typedef uint32_t uint32_8 __attribute__ ((vector_size (8 * sizeof(uint32_t))));
static void Picture_render(Picture *p, SDL_Renderer *rend) {
uint32_8 c = p->color - (uint32_8){};
uint32_8 y = 0 - (uint32_8){};
for (int j = p->y1, r = 0; j < p->y2; j++, y+=1) {
uint32_8 x = {0, 1, 2, 3, 4, 5, 6, 7};
for (int i = p->x1; i < p->x2; i+=8, r+=8, x+=8) {
uint32_8 z = (x ^ y) % 9;
uint32_8 f = (z==0) & c;
memcpy(&p->pixels[r], (uint32_t*)&f, sizeof(f));
}
}
if (p->texture) SDL_DestroyTexture(p->texture);
p->texture = SDL_CreateTextureFromSurface(rend, p->surface);
SDL_SetTextureBlendMode(p->texture, SDL_BLENDMODE_NONE);
}
static void Picture_move(Picture *p, int x, int y) {
p->x1 += x;
p->x2 += x;
p->y1 += y;
p->y2 += y;
}
struct int2 { int x; int y; };
int main() {
int w = 1280, h = 720;
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
fprintf(stderr, "Can't init: %s\n", SDL_GetError());
return -1;
}
SDL_Window *window = SDL_CreateWindow("xormod",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, w, h,
ACCEL_PLATFORM | SDL_WINDOW_FULLSCREEN);
if (window == NULL) {
fprintf(stderr, "Can't open window: %s\n", SDL_GetError());
return -1;
}
SDL_GetWindowSize(window, &w, &h);
SDL_Renderer *rend = SDL_CreateRenderer(window, -1,
SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
SDL_Texture *font = load_font(rend);
Picture *pictures[4];
enum { P_TOPLEFT, P_TOPRGHT, P_BOTLEFT, P_BOTRGHT };
pictures[P_TOPLEFT] = Picture_new(rend, 0, 0, w, h, 0xff7fffff);
pictures[P_TOPRGHT] = Picture_new(rend, w, 0, w, h, 0xffff7fff);
pictures[P_BOTLEFT] = Picture_new(rend, 0, h, w, h, 0xffffff7f);
pictures[P_BOTRGHT] = Picture_new(rend, w, h, w, h, 0xff7fff7f);
struct int2 off = { 0, 0 };
struct int2 mouse_prev = { -1, -1 };
int running = 1;
while (running) {
const uint8_t *keys = SDL_GetKeyboardState(NULL);
if (keys[SDL_SCANCODE_ESCAPE] || keys[SDL_SCANCODE_Q]) {
break;
}
if (keys[SDL_SCANCODE_LEFT]) {
off.x -= 16;
}
if (keys[SDL_SCANCODE_RIGHT]) {
off.x += 16;
}
if (keys[SDL_SCANCODE_UP]) {
off.y -= 16;
}
if (keys[SDL_SCANCODE_DOWN]) {
off.y += 16;
}
struct int2 mouse;
if (SDL_GetMouseState(&mouse.x, &mouse.y) & SDL_BUTTON(SDL_BUTTON_LEFT)) {
if (mouse_prev.x != -1 ) {
off.x -= mouse.x - mouse_prev.x;
off.y -= mouse.y - mouse_prev.y;
}
mouse_prev = mouse;
} else if (mouse_prev.x != -1) {
mouse_prev = (struct int2) { -1, -1 };
}
if (off.y < pictures[P_TOPLEFT]->y1) {
SWAP(pictures[P_TOPLEFT], pictures[P_BOTLEFT]);
SWAP(pictures[P_TOPRGHT], pictures[P_BOTRGHT]);
Picture_move(pictures[P_TOPLEFT], 0, -2*h);
Picture_move(pictures[P_TOPRGHT], 0, -2*h);
Picture_render(pictures[P_TOPLEFT], rend);
Picture_render(pictures[P_TOPRGHT], rend);
}
if (off.x < pictures[P_TOPLEFT]->x1) {
SWAP(pictures[P_TOPLEFT], pictures[P_TOPRGHT]);
SWAP(pictures[P_BOTLEFT], pictures[P_BOTRGHT]);
Picture_move(pictures[P_TOPLEFT], -2*w, 0);
Picture_move(pictures[P_BOTLEFT], -2*w, 0);
Picture_render(pictures[P_TOPLEFT], rend);
Picture_render(pictures[P_BOTLEFT], rend);
}
if (off.y > pictures[P_BOTRGHT]->y1) {
SWAP(pictures[P_TOPLEFT], pictures[P_BOTLEFT]);
SWAP(pictures[P_TOPRGHT], pictures[P_BOTRGHT]);
Picture_move(pictures[P_BOTLEFT], 0, 2*h);
Picture_move(pictures[P_BOTRGHT], 0, 2*h);
Picture_render(pictures[P_BOTLEFT], rend);
Picture_render(pictures[P_BOTRGHT], rend);
}
if (off.x > pictures[P_BOTRGHT]->x1) {
SWAP(pictures[P_TOPLEFT], pictures[P_TOPRGHT]);
SWAP(pictures[P_BOTLEFT], pictures[P_BOTRGHT]);
Picture_move(pictures[P_TOPRGHT], 2*w, 0);
Picture_move(pictures[P_BOTRGHT], 2*w, 0);
Picture_render(pictures[P_TOPRGHT], rend);
Picture_render(pictures[P_BOTRGHT], rend);
}
//SDL_SetRenderDrawColor(rend, 0, 0, 0, 255);
//SDL_RenderClear(rend);
for (int i = 0; i < 4; i++) {
Picture *p = pictures[i];
SDL_Rect dst = {
p->x1 - off.x, p->y1 - off.y, w, h,
};
SDL_RenderCopy(rend, p->texture, NULL, &dst);
}
//char buf[72];
//SDL_SetRenderDrawColor(rend, 0, 0, 0, 255);
//SDL_RenderFillRect(rend, &(SDL_Rect) { 0, 0, sizeof(buf)*font_w, 7*font_h });
//size_t len = snprintf(buf, sizeof(buf), "off.x: %d, off.y: %d", off.x, off.y);
//draw_text(rend, font, buf, len, RC(1, 1), 255, 255, 255);
//char *q[] = {"TL", "TR", "BL", "BR"};
//for (int i = 0; i < 4; i++) {
// Picture *p = pictures[i];
// len = snprintf(buf, sizeof(buf), "%s| x1: %05d, x2: %05d, y1: %05d, y2: %05d, p: %p",
// q[i], p->x1, p->x2, p->y1, p->y2, p);
// draw_text(rend, font, buf, len, RC(2+i, 1), 255, 255, 255);
//}
//draw_text(rend, font, ACCEL_PLATFORM_STR, sizeof(ACCEL_PLATFORM_STR), RC(1,1), 255, 255, 255);
SDL_RenderPresent(rend);
SDL_Event e;
while (SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT) {
running = 0;
}
}
}
SDL_DestroyRenderer(rend);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}