Home
Admin | Edit

Code snippets

Contents

Note : Most of the code here is C compiled with GCC. The code embed a shell script to compile itself so just run : sh code.c

C / Shell : Standalone single file compilation / execution (self-executable C file)

A C / Shell trick to pack the code, compilation and execution of a C program into a single file which is useful for short programs, prototypes, debugging or to show off C examples, put this into a test.c file and run it with sh test.c :
#ifdef d
#!/bin/sh
gcc -Wall -O0 test.c -o out
./out
exit
#endif

// your usual C code

C / x86 : SIMD debugging / exploration (with intrinsics)

This is a program i did as an exploration / debugging tool when i started to use SIMD instructions, it use compiler intrinsics (see the intrinsics guide) and just print the content of SIMD registers (here AVX), quite useful to quickly evaluate the result of some SIMD code. Just put it into a simd.c file and run it with sh simd.c :
#ifdef d
#!/bin/sh
gcc -Wall -mavx2 -m32 -O0 simd.c -o out
./out
exit
#endif

#include <stdio.h>
#include <x86intrin.h>

float input2[8] = {
    0.75f, 0.5f, 0.25f, 0.0f
};
float output[8] = {
    0
};

int main (void) {
    __m256i i1i = _mm256_set_epi32(0, 0, 0, 0, 0, 6, 4, 2);
    __m256 v1 = _mm256_cvtepi32_ps(i1i);
    __m256 i2 = _mm256_loadu_ps(&input2[0]);
    __m256 v2 = _mm256_mul_ps(v1, i2);
    __m256 v3 = _mm256_hadd_ps(v2, v2);
    _mm256_storeu_ps((float *)output, v3);

    for (int i = 0; i < 8; i += 1) {
        printf("%f ", output[i]);
    }
    printf("\n");

    return 0;
}

C Raspberry PI Zero 1.3 U-Boot bare metal sample

Quick way for bare metal PI Zero C program with U-Boot, only require a GCC for the target platform and Das U-Boot, on Ubuntu : sudo apt-get install gcc-arm-linux-gnueabihf

Might work without U-Boot but untested, this will produce a minimal binary which can be a starting point though but might require more initialization code without U-Boot and address will be likely 0x8000 instead of 0x80000.

This produce a sample.bin file which can be copied to a SD card with all the others proprietary PI blobs along with U-Boot binary and configuration stuff (config.txt etc.)

In U-Boot prompt you can then load and run the binary (can be automated as well in U-Boot config.) :
fatload usb 0:1 0x80000 sample.bin
go 0x80000

sample.c :
#ifdef d
#!/bin/sh
set -e

rm -f *.o *.elf *.bin
arm-linux-gnueabihf-as --warn --fatal-warnings start.s -o start.o
arm-linux-gnueabihf-gcc -Wall -O3 -march=armv6 -mtune=arm1176jzf-s -mfloat-abi=soft -ffreestanding -nostdlib -c sample.c -o sample.o
arm-linux-gnueabihf-ld -T rpi0.ld -nostdlib start.o sample.o -o sample.elf
arm-linux-gnueabihf-objcopy sample.elf -O binary sample.img
#arm-linux-gnueabihf-objdump -D -b binary -m arm sample.img --adjust-vma=0x80000
rm *.o *.elf
wc -c sample.img
exit
#endif

void main() {
    while (1) {

    }
}

rpi0.ld :
ENTRY(_start)

MEMORY
{
    ram : ORIGIN = 0x80000, LENGTH = 0x1000000
}
SECTIONS
{
    .text : { *(.text) } > ram
    .data : { *(.data) } > ram
    .bss : { *(.bss) } > ram
}

start.s :
.global _start

.section .text
_start:
    ldr sp, =0x80000
    bl main
    b .

Can also see standalone U-Boot examples.

JavaScript : Extended Cistercian numerals (base 16 and binary-like)

p5js code to generate an extended version of Cistercian numerals programmatically, this can generate pages of numerals, this sample display the executable binary of one of my tiny intro as Cistercian numerals

Here is a complete example result with many of my intros packed into a tiny space.

// modified "Cistercian" numerals : binary-like and extended to base 16 (1 to 65535 range), a whole glyph is 16-bit
// the binary like property makes it simpler as the drawing is done per nibble,
// the 4 original (original = corresponding Cistercian glyph) features below are
// only needed to draw the rest of the nibble digits by layering / composition :
//  0001 -> original 1
//  0010 -> original 2
//  0100 -> original 4
//  1000 -> original 6
// then to draw nibble values :
//  0110 -> draw original 2 and draw original 4
//  1001 -> draw original 1 and draw original 6
// then the rest of the nibbles are drawn on the 3 other sides with conventional order :
//  upper right, upper left, lower right, lower left
// can either use vertical stave or a dot
// https://en.wikipedia.org/wiki/Cistercian_numerals
// another fun notation is Bibi-binary : https://en.wikipedia.org/wiki/Bibi-binary
let b = [
  // memph32.com executable binary (DOS 32b)
  [
    0xb01389d5, 0xd1fd11e9, 0x29ca19c1, 0x60c1e908, 0xc1ea0930, 0xc6cd1061, 0xb40c3fe2, 0xe540ebe2,
    0,          0,          0,          0,          0,          0,          0,          0
  ],
]

function setup() {
  createCanvas(682, 564)
  background(0)
 
  noLoop()
}

function draw() {
  let glylen = 4 // length of a mark
  let offset = 22 + 22 * width // draw offset
  let spacing = 2 // space between glyph
  let line_spacing = 2 // space between lines
  let cl = 0 // current line
  let stave = false // draw vertical stave ? otherwise draw a centered dot to identify 0
 
  loadPixels()
  for (let ln = 0; ln < b.length; ln += 1) {
    let data = b[ln]
    
    let cr = 128 + random(128) | 0
    let cg = 128 + random(128) | 0
    let cb = 128 + random(128) | 0
    
    // put data on other "pages" when it reach a treshold
    if ((ln + 1) % 12 == 0) offset += 328 - 520 * width

    let x = 0
    for (let i = 0; i < data.length; i += 1) {
      let n = b[ln][i]
      
      // wrap line to 16x32 bit value
      if (i != 0 && (i & 15) == 0) {
        x = 0
        cl += 1
      }

      let xs = 1
      let ys = 1
      let oy = cl * ((glylen << 1) + line_spacing)
      let y = oy
      for (let b = 1; b < 32; b += 4) {
        let nb = (n >> (15 + b)) & 15

        if (b == 1 || b == 17) {
          xs = 1
          ys = 1
          y = oy

          if (b == 17) {
            x += (glylen << 1) + spacing
          }
          
          // draw stave
          if (stave) {
            for (let l = 0; l <= (glylen << 1); l += 1) {
              let index = (offset + x + (y + l) * width) * 4
              pixels[index + 0] = cr
              pixels[index + 1] = cg
              pixels[index + 2] = cb
            }
          } else {
            let index = (offset + x + (y + glylen) * width) * 4
            pixels[index + 0] = cr
            pixels[index + 1] = cg
            pixels[index + 2] = cb
          }
        }

        // horizontal flip
        if (b == 5 || b == 13 || b == 21 || b == 29) {
          xs = -1
        }

        // vertical flip
        if (b == 9 || b == 25) {
          xs = 1
          ys = -1
          y += (glylen << 1)
        }

        // draw nibble features on previously configured quadrant
        if ((nb >> 0) & 1) {
          for (let l = 0; l <= glylen; l += 1) {
            let index = (offset + x + l * xs + y * width) * 4
            pixels[index + 0] = cr
            pixels[index + 1] = cg
            pixels[index + 2] = cb
          }
        }

        if ((nb >> 1) & 1) {
          for (let l = 0; l <= glylen; l += 1) {
            let index = (offset + x + l * xs + (y + glylen * ys) * width) * 4
            pixels[index + 0] = cr
            pixels[index + 1] = cg
            pixels[index + 2] = cb
          }
        }

        if ((nb >> 2) & 1) {
          for (let l = 0; l <= glylen; l += 1) {
            let index = (offset + x + l * xs + (glylen * ys + y - l * ys) * width) * 4
            pixels[index + 0] = cr
            pixels[index + 1] = cg
            pixels[index + 2] = cb
          }
        }

        if ((nb >> 3) & 1) {
          for (let l = 0; l <= glylen; l += 1) {
            let index = (offset + x + glylen * xs + (y + l  * ys) * width) * 4
            pixels[index + 0] = cr
            pixels[index + 1] = cg
            pixels[index + 2] = cb
          }
        }
      }

      // next glyph
      x += (glylen << 1) + spacing
    }
    // next line
    cl += 1
  }
  updatePixels()
}

Bash : Format directory files raw data into an array of hex / 32-bit chunks

This was used as a source to the Cistercian program above to generate my tiny executable binaries as Cistercian glyphs.

#!/bin/bash

# Directory containing the binary files
DIRECTORY="/home/binaries"
OUTPUT_FILE="output.txt"

# Clear the output file if it exists
> "$OUTPUT_FILE"

# Loop through all files in the directory
for file in $(find "$DIRECTORY" -type f -exec du -b {} + | sort -nr | awk '{print $2}'); do
    if [ -f "$file" ]; then
        filename=$(basename "$file")
        echo "// $filename" >> "$OUTPUT_FILE"
        echo "[" >> "$OUTPUT_FILE"

        # Convert binary file to hex, format in 32-bit chunks, and modify format
        xxd -p -c 4 "$file" | awk '
        {
            # Ensure the hex dump is padded to exactly 8 characters (32-bit)
            hex_value = sprintf("0x%08s", $0);
            gsub(" ", "0", hex_value); # Replace spaces with zeroes

            printf "%s%s", hex_value, (NR % 8 == 0 ? ",\n" : ", ");
        }' >> "$OUTPUT_FILE"

        echo "]," >> "$OUTPUT_FILE"  # Closing bracket on a new line

        echo "Processed: $file"
    fi
done

echo "All files have been processed and saved in $OUTPUT_FILE."


back to topLicence Creative Commons