Compare commits

..

No commits in common. "rewrite" and "main" have entirely different histories.

17 changed files with 422 additions and 102887 deletions

View file

@ -4,14 +4,12 @@ PREFIX ?= /usr/local
CFLAGS := $(CFLAGS) `pkg-config --cflags --libs sdl3`
LDFLAGS := $(LDFLAGS) -lm
SRCS = sp.c
SRCS = slutpet.c img.c samply.c sdl.c
all: slutpet
slutpet: ${SRCS} s7.o
s7.o: s7.c
slutpet: ${SRCS}
.PHONY: clean
clean:
-rm -f slutpet s7.o
-rm -f slutpet

34
dat.h Normal file
View file

@ -0,0 +1,34 @@
typedef struct Samply Samply;
typedef struct Image Image;
typedef struct State State;
struct Samply {
Image *tx; /* this is a pointer to one of the images below */
Image *idle;
Image *walka;
Image *walkb;
Image *error;
};
struct Image {
char *name; /* used for debugging purposes */
int w;
int h;
int bpp;
unsigned char *data;
SDL_Surface *sur;
SDL_Texture *tex;
};
struct State {
SDL_Window *win;
SDL_Renderer *ren;
SDL_DisplayID dpy;
SDL_Rect bounds;
Uint64 lastframe;
Uint64 frame;
Samply *sam;
};

13
fns.h Normal file
View file

@ -0,0 +1,13 @@
#define babble(...) SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__)
#define info(...) SDL_Log(__VA_ARGS__)
#define shit(...) SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__)
#define fuck(...) SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, __VA_ARGS__)
void free_image(Image *i);
Image *load_image(SDL_Renderer *ren, char *path);
int samply_step(State *st);
void put_samply_to_bed(Samply *sam);
Samply *wake_samply_up(State *st);
int in_bounds(Image *i, int x, int y, SDL_Rect *bounds);

88
img.c Normal file
View file

@ -0,0 +1,88 @@
#define STB_IMAGE_IMPLEMENTATION
#define STBI_MALLOC(sz) SDL_malloc(sz)
#define STBI_REALLOC(p,newsz) SDL_realloc(p,newsz)
#define STBI_FREE(p) SDL_free(p)
#include <SDL3/SDL.h>
#include "stb_image.h"
#include "dat.h"
#include "fns.h"
void
free_image(Image *i)
{
if (i) {
if (i->tex) {
babble("free img %s texture...", i->name);
SDL_DestroyTexture(i->tex);
}
if (i->sur) {
babble("destroy image %s surface...", i->name);
SDL_DestroySurface(i->sur);
}
if (i->data) {
babble("free img %s data...", i->name);
stbi_image_free(i->data);
}
if (i->name) {
babble("free img %s name...", i->name);
SDL_free(i->name);
}
babble("free aforementioned img...");
SDL_free(i);
}
}
Image *
load_image(SDL_Renderer *ren, char *path)
{
Image *i;
babble("create image %s...", path);
babble("alloc image...", path);
i = SDL_calloc(1, sizeof(Image));
if (!i) {
shit("mem alloc fail: %s", SDL_GetError());
return NULL;
}
babble("alloc image %s name...", path);
i->name = SDL_strdup(path);
if (!i->name) {
shit("strdup fail: %s", SDL_GetError());
free_image(i);
return NULL;
}
babble("alloc image %s data...", i->name);
i->data = stbi_load(path, &i->w, &i->h,
&i->bpp, 4);
if (!i->data) {
shit("img load fail: %s", stbi_failure_reason());
free_image(i);
return NULL;
}
babble("alloc image %s surface...", i->name);
i->sur = SDL_CreateSurfaceFrom(i->w, i->h,
SDL_PIXELFORMAT_RGBA32, i->data,
i->w * 4);
if (!i->sur) {
shit("surface creation fail: %s", SDL_GetError());
free_image(i);
return NULL;
}
babble("alloc image %s texture...", i->name);
i->tex = SDL_CreateTextureFromSurface(ren, i->sur);
if (!i->tex) {
shit("surface creation fail: %s", SDL_GetError());
SDL_DestroySurface(i->sur);
free_image(i);
return NULL;
}
babble("image %s created", path);
return i;
}

53
readme
View file

@ -1,46 +1,19 @@
design (+ usage)
horny desktop pet thing.
(this is for now just a design document and not describing the actual program.)
you need sdl3 to build it.
i have not tried cross-compiling to windows yet.
slutpet makes use of s7 scheme as a scripting language.
(this, by the way, is why the program takes a weirdly long time to compile --
s7.{c,h} contain the entire s7 scheme interpreter, over 100,000 lines.)
if you don't know scheme,
a) don't worry, it's pretty simple, and
b) sorry in advance.
i think it's probably best to use some sort of extension language.
i want people to be able to create their own pets without having to
figure out how to recompile.
c source files:
run it with `SDL_LOGGING=app=debug ./slutpet` for verbose logging
sp.c: main entry, exit, event/render loops
file layout:
a pet is implemented by setting the variable 'pet' to
an alist (is this the correct term?) which contains some values.
setting the pet variable should handle this automatically,
but various hooks can then be set, which will be executed
whenever a certain event has happened.
dat.h - data structure header
fns.h - functions and macros header
list of variables:
pet: the pet that the program will use. this is a list of cons that define the pet.
TODO: maybe this should be a macro that sets other variables.
pet-name: string containing the pet's name.
list of hooks:
pre-init-hook: before anything has happened at all; right after s7 has been initialised.
this is also before any init files have been read
post-init-hook: when the window has been set up and things are ready to happen.
the current pet should be set and initialised by this point.
tick-hook: every program tick. the pet's drawing information should be set
here so it can be rendered.
TODO: figure out what to do about event hooks
pre-quit-hook: the program is about to exit, no de-init things have been done yet.
post-quit-hook: everything (except, obviously, the s7 interpreter) has been de-initialised.
list of functions:
(load-image path): set up a new image, with the data taken from the given path.
this will return the a list of cons pairs with the image data,
in a form that can be used in the pet variable.
(free-image image): free heap-allocated data in image.
list of c-types:
pixmap: the data created from stb-image.
slutpet.c - sdl init and close
img.c - loading images
samply.c - pet Samply

101531
s7.c

File diff suppressed because it is too large Load diff

1307
s7.h

File diff suppressed because it is too large Load diff

110
samply.c Normal file
View file

@ -0,0 +1,110 @@
#include <SDL3/SDL.h>
#include "dat.h"
#include "fns.h"
int
samply_step(State *st)
{
Uint64 ms;
int x, y;
if (SDL_GetWindowPosition(st->win, &x, &y) == false) {
shit("window pos query fail: %s", SDL_GetError());
goto render_it;
}
ms = SDL_GetTicks();
if ((ms / 100) % 2) {
babble("anim walka");
st->sam->tx = st->sam->walka;
} else {
babble("anim walkb");
st->sam->tx = st->sam->walkb;
}
x++;
babble("bounds %d %d %d %d", st->bounds.x, st->bounds.y,
st->bounds.w, st->bounds.h);
babble("img %d %d %d %d", x, y, st->sam->tx->w / 4, st->sam->tx->h);
// if (in_bounds(st->sam->tx, x, y, &st->bounds) == false) {
if (st->bounds.w - st->sam->tx->w / 4 < x) {
st->sam->tx = st->sam->idle;
x = st->bounds.w - st->sam->tx->w / 4;
babble("*bonk*");
}
if (SDL_SetWindowPosition(st->win, x, y) == false)
shit("window pos set fail: %s", SDL_GetError());
render_it:
if (SDL_RenderTexture(st->ren, st->sam->tx->tex, NULL, NULL) == false) {
fuck("rendertexture fail: %s", SDL_GetError());
return -1;
}
}
void
put_samply_to_bed(Samply *sam)
{
if (sam) {
babble("free samply idle!!");
free_image(sam->idle);
babble("free samply walk a!!");
free_image(sam->walka);
babble("free samply walk b!!");
free_image(sam->walkb);
babble("free samply woozy!!");
free_image(sam->error);
babble("good night, samply!!");
SDL_free(sam);
}
}
Samply *
wake_samply_up(State *st)
{
Samply *sam;
babble("wake up, samply!!");
sam = SDL_calloc(1, sizeof(Samply));
if (!sam) {
fuck("samply would rather stay in bed. too bad! %s", SDL_GetError());
return NULL;
}
babble("stand samply up!!");
sam->idle = load_image(st->ren, "samply/Samply.png");
if (!sam->idle) {
fuck("samply would rather stay in bed. too bad!");
put_samply_to_bed(sam);
return NULL;
}
babble("samply walk! part 1!!");
sam->walka = load_image(st->ren, "samply/Samply_Walk1.png");
if (!sam->walka) {
fuck("samply would rather stay in bed. too bad!");
put_samply_to_bed(sam);
return NULL;
}
babble("samply walk! part 2!!");
sam->walkb = load_image(st->ren, "samply/Samply_Walk2.png");
if (!sam->walkb) {
fuck("samply would rather stay in bed. too bad!");
put_samply_to_bed(sam);
return NULL;
}
babble("samply woozy!!");
sam->error = load_image(st->ren, "samply/SamplyERROR.png");
if (!sam->error) {
fuck("samply would rather stay in bed. too bad!");
put_samply_to_bed(sam);
return NULL;
}
sam->tx = sam->idle;
return sam;
}

BIN
samply/Samply.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

BIN
samply/SamplyERROR.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

BIN
samply/Samply_Walk1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

BIN
samply/Samply_Walk2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

3
samply/readme Normal file
View file

@ -0,0 +1,3 @@
theyre very hasty
h/t zyre for drawing these

17
sdl.c Normal file
View file

@ -0,0 +1,17 @@
#include <SDL3/SDL.h>
#include "dat.h"
#include "fns.h"
int
in_bounds(Image *i, int x, int y, SDL_Rect *bounds)
{
SDL_Rect r;
SDL_Rect irect = { x, y, i->w, i->h };
if (SDL_GetRectUnion(&irect, bounds, &r) == false) {
shit("rect union math fail: %s", SDL_GetError());
return false;
}
return SDL_RectsEqual(&irect, &r);
}

17
slutpet.6 Normal file
View file

@ -0,0 +1,17 @@
.Dd May 24, 2025
.Dt SLUTPET 6
.Os
.
.Sh NAME
.Nm slutpet
.Nd a desktop pet for perverts
.
.Sh SYNOPSIS
.Nm
.
.Sh DESCRIPTION
.Nm
.Em will
be a desktop pet thing,
but currently it doesn't actually exist.
Try again later.

124
slutpet.c Normal file
View file

@ -0,0 +1,124 @@
#define SDL_MAIN_USE_CALLBACKS
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include "stb_image.h"
#include "dat.h"
#include "fns.h"
void
SDL_AppQuit(void *as, SDL_AppResult res)
{
State *st;
st = as;
if (st) {
babble("put samply to bed!!");
put_samply_to_bed(st->sam);
babble("free state...");
SDL_free(st);
}
babble("bye!");
return;
}
SDL_AppResult
SDL_AppEvent(void *as, SDL_Event *ev)
{
switch (ev->type) {
case SDL_EVENT_MOUSE_BUTTON_DOWN:
babble("mouse button down event");
if (ev->button.button == SDL_BUTTON_RIGHT) {
babble("right-click quit requested");
return SDL_APP_SUCCESS;
}
break;
case SDL_EVENT_QUIT:
babble("quit requested");
return SDL_APP_SUCCESS;
break; /* unreachable; here for visual symmetry */
}
return SDL_APP_CONTINUE;
}
SDL_AppResult
SDL_AppIterate(void *as)
{
State *st = as;
SDL_Texture *tx;
Uint64 ms;
st->frame++;
SDL_SetRenderDrawColor(st->ren, 0, 0, 0, SDL_ALPHA_TRANSPARENT);
SDL_RenderClear(st->ren);
if (samply_step(st) < 0)
return SDL_APP_FAILURE;
SDL_RenderPresent(st->ren);
st->lastframe = SDL_GetTicks();
return SDL_APP_CONTINUE;
}
SDL_AppResult
SDL_AppInit(void **as, int argc, char **argv)
{
State *st;
babble("init sdl...");
if (!SDL_Init(SDL_INIT_VIDEO)) {
fuck("sdl init fail: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
babble("alloc state...");
st = SDL_calloc(1, sizeof(State));
if (!st) {
fuck("mem alloc fail: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
*as = st;
SDL_SetHint(SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT, "1");
st->lastframe = SDL_GetTicks();
st->frame = 0;
babble("create win+render...");
if (!SDL_CreateWindowAndRenderer("slutpet", 320, 320,
SDL_WINDOW_TRANSPARENT | SDL_WINDOW_BORDERLESS
| SDL_WINDOW_NOT_FOCUSABLE
| SDL_WINDOW_ALWAYS_ON_TOP,
&st->win, &st->ren)) {
fuck("win creation fail: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (SDL_EnableScreenSaver() == false)
shit("cannot disable screensaver: %s", SDL_GetError());
st->dpy = SDL_GetDisplayForWindow(st->win);
if (!st->dpy) {
fuck("cannot get current display: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (SDL_GetDisplayBounds(st->dpy, &st->bounds) == false) {
fuck("cannot get display bounds: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
babble("create samply!!...");
st->sam = wake_samply_up(st);
if (!st->sam) {
fuck("samply said no. too bad!");
return SDL_APP_FAILURE;
}
babble("hi!!");
babble("program startup took %llums!", SDL_GetTicks());
return SDL_APP_CONTINUE;
}

4
sp.c
View file

@ -1,4 +0,0 @@
#define SDL_MAIN_USE_CALLBACKS
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include "s7.h"