index posts opinions portfolio


My posts about programming and things.
Date format is day/month/year because I'm sane.

prev 1 2 3 4 5 6 7 8 9 10 11 12 13 next

simple grid-based and ncurses minesweeper


I've been interested in minesweeper lately so I wrote a simple grid version in C as well as one using ncurses.

You can find the source code in my git repo.

Cropped Yuu's face too


Similar to Chito previously, I cropped out every Yuu face from Bloom Into You totalling 2325 images.

You can find them at https://gnupluslinux.com/yuu/ and download a zip containing every image sorted by chapter and ordered here.

Who cares for the details but, I used xbindkeys to create a shortcut that launches a script. This script uses scrot to take a cropped screenshot into a directory.

During the cropping of all faces I used feh to view images in order using `ls -1 -rt | xargs feh`. This will list the directory, show only file names, reverse the order and order them by modification time.

The file name is randomised, so to order them I needed to use the files modification time. To do this I used a simple bash script: `n=0; ls -tr | while read i; do n=$((n+1)); mv -- "$i" "$(printf %03d "$n").png"; done`. This renames every image in order (001.png, 002.png ...). I took care to use the `preserve` flag in cp (copy) to preserve the modification date when copying around.

Next I had to compress the images, to do this I used pngquant `pngquant --quality=65-80 * --ext .png --force`.

To prevent having to run the script manually in each chapter directory one at a time I ran them in a loop `for d in chapter*; do ( cd "$d" && ../../script.sh ); done`.

After compression the total file size for all images went from 138MB to 52MB.

Then I had to somehow turn these images files into html files. To do this I wrote a simple Python script that iterates through every chapter and image and generates the pages and navigation bars.

The python script:


import glob

outputdir = "out/"                                  # directory to output html
templatefile = "template.txt"                       # template file
imgglob = "*.png"                                   # glob for image files
nochapters = 45;                                    # number of chapters to include
localimgloc = "../"                                 # location of images on filesystem (../chapterx)
dirprefix = "chapter";                              # prefix for chapter directories
imgloc = "https://gnupluslinux.com/anime/yuu/";     # location of images
                                                    # final will be imgloc+dirprefix+chapternumber
                                                    # (https://gnupluslibux.com/anime/yuu/chapterx/001.png)

def getimgno(chapter):
    get number of images in chapter
    return  len(glob.glob1("%s/%s%s" % (localimgloc, dirprefix, str(chapter)), imgglob))

def generatenavbar(chapter):
    generate navigation bar for chapter
    bar = "Chapter: ";
    for p in range(1, nochapters+1):
        if p == chapter:
            # handle own chapter specially
            bar += "<strong>%s</strong> " % (str(p));
            bar += "<a href=\"%s%s.html\">%s</a> " % (dirprefix, str(p), str(p));
    return bar;

def generateimages(chapter):
    imgcount = getimgno(chapter);
    images = "";
    for p in range(1, imgcount+1):
        images += "<a href=\"%s/%s%s/%03d.png\"> <img src=\"%s/%s%s/%03d.png\" alt=\"Yuu face #%s\"></a>\n" \
        % (imgloc, dirprefix, str(chapter), p, imgloc, dirprefix, str(chapter), p, p);
    return images;

def generatepages():
    call all functions and generate/output final html
    for p in range(1, nochapters+1):
        navbar = generatenavbar(p);
        # read template into memory
        templatedata = "";
        with open (templatefile, 'r') as template:
            templatedata = template.read();
        #insert title
        templatedata = templatedata.replace("{TITLE}", "Yuu's face in chapter %s" % p); 
        # insert navbar
        templatedata = templatedata.replace("{NAVBAR}", navbar);
        #insert images
        images = generateimages(p);
        templatedata = templatedata.replace("{IMAGES}", images);
        # write to output file
        with open("%s/%s%s.html" % (outputdir, dirprefix, p), 'w') as out:

def main():

if __name__ == "__main__":

router and too much free time


Recently I purchased a netgear wndr3800 router which now runs librecmc. Now my main system (x200 with libre(core)boot) and router run more free software.

I also spent a day taking a screenshot of every Chito face (1505 of them) from the manga Girl's Last Tour because she's really cute. I have them online in a collage like thing at https://gnupluslinux.com/chito/. You can download all 1505 images here.

cheeky chito

Simple stack


I'm exploring data structures and I find I learn best when I put something out, so first with a stack. This is my simple implementation using an array. A linked list would be better but that's more verbose.

 * stack using array
#include <stdio.h>
#include <stdlib.h>

struct stack
	ssize_t size;
	ssize_t top;
	int *array;

struct stack
*createstack(size_t size)
	struct stack *stack = malloc(sizeof(struct stack));
	stack->size = size;
	stack->top = -1;
	stack->array = malloc(sizeof(int) * stack->size);
	return stack;

destroystack(struct stack *stack)

isempty(struct stack *stack)
	return (stack->top == -1);

pushstack(struct stack *stack, int val)
	if (stack->top+1 > stack->size)
		fprintf(stderr, "stack is full, can't push\n");
	stack->array[stack->top] = val;

popstack(struct stack *stack)
	if (isempty(stack))
		fprintf(stderr, "stack is empty, can't pop\n");
		/* in the real world we would not be holding ints so -1 will do */
		return -1;
	int popped = stack->array[stack->top];
	return popped;

peekstack(struct stack *stack)
	if (isempty(stack))
		fprintf(stderr, "stack is empty, can't peek\n");
		return -1;
	return stack->array[stack->top];

printstack(struct stack *stack)
	if (isempty(stack))
		fprintf(stderr, "stack is empty\n");
	for (ssize_t i = 0; i <= stack->top; i++)
		printf("[%zd] = %d\n", i, stack->array[i]);

	struct stack *stack = createstack(50);
	printf("isempty: %d\n", isempty(stack));
	pushstack(stack, 5);
	pushstack(stack, 10);
	pushstack(stack, 15);
	printf("peek: %d\n", peekstack(stack));
	printf("isempty: %d\n", isempty(stack));
	printf("popped: %d\n", popstack(stack));
	printf("popped: %d\n", popstack(stack));
	printf("popped: %d\n", popstack(stack));
	return 0;

Librebooted my x200


Today I finally librebooted my thinkpad x200. This wont be a full tutorial because a million people have done that, instead it will be a collection of things I had to figure out and whatnot.

tl;dr: I followed this tutorial and it worked fine. Though there was an error in the pinout diagram they provide, my corrected version: (click to see larger picture)

First let me say the libreboot install docs were hard for me to follow logically with how it is laid out and the research you are expected to do first.

Now for some pictures of the process:

Checked the BIOS and ECC versions are the latest:

Completed the required laptop disassembly:

Wired up the pi as required:

Put the clip on and connected it to the pi correctly:

Replaced the wifi card:

First boot:

From here, I migrated the Arch install to Parabola and life was free.

Got an x200T and some figures, libreboot tools


I purchased an x200T for reading manga (and because thinkpads are sexy as fuck). It has 6GB memory and came with a 120GB SanDisk SSD. The keyboard is a shitty replacement, which is unfortunate. Original charger, new (probably shitty) battery, pen (needed a good clean with IPA, it was very sticky and gross) and nice conditioned lid. I don't intend to libreboot this one anytime soon, though.

I also purchased 2 Girl's Last Tour Nendroids and the Girl's Last Tour premium boxset.

I've also purchased a raspberry pi zero w and a soic-16 clip for librebooting my x200. I had 3 pi's but they are all dead, so I needed a new one. I could have used my bluepill devboard, however that looked harder as there were no tutorials on using it.

I did also buy a ch341a USB programmer to use as a librebooting tool, however its voltages are completely wrong.

website generator RSS support


I added RSS support to the website generator. This blogs RSS stream can be found here.

The source code can be found in my git repo.

website generator re-written in C


For the last week or so I have been re-writing my static website genertor in C (again), but this time I finished it. This website is now generated using it.

The source code can be found in my git repo.

status bar (binstatus) changes


I've rewritten my status bar that I use for dwm. It is now completely dynamic and allows customisation through a config.h header file. Yes, I am copying the suckless way of doing things - it's great.

The bar looks like this currently:
(time, battery percent, battery status - D for discharging battery)

The status bar is customised by changing an array that consists of structs. The struct used contains a pointer to a function and a flag (integer). You can use any of the provided functions (see components.h) as a part of the struct. Adding your own is easy, they must just return a char *.

static const struct component components[] ={
	 /*      function        flag    */
	        {currenttime,   NORMALTIME|SHOWMERIDIEM},
	        {battery,       NONE},
	        {charging,      NONE},
The image above was made using this array. If you so desire, you can add more clocks, or any other component, just add another array element. The components are drawn in order.

Flags currently include: 12 hour time, 24 hour time, time shown in binary and whether to show AM/PM. (OR the flags together)

The source code can be found in my git repo.

Got some things


I've purchased a few cool things lately:

I finally got a thinkpad x200! A friend found the listing on ebay - it was a reasonable price compared to everything else available. 4GB ram, no damage, some scratches on the lid. I am yet to libreboot it, but that is the plan. There will be a post on doing that at some point.

I have purchased a new SSD for my desktop, so this x200 will eventually get the SSD that was in that. Or I will just buy a cheap one. Honestly, the HDD is fast enough for me.

I also got some figures, wall scrolls and a boxset. The pictures are shit and don't represent real colors and detail... The yagate scroll is shit in real life, though.

prev 1 2 3 4 5 6 7 8 9 10 11 12 13 next

RSS feed
FSF member

page generated 9/1/2022 using websitegenerator in C