Compare commits
6 Commits
9f101abc10
...
master
Author | SHA1 | Date | |
---|---|---|---|
3c0c510a0d
|
|||
aa3dcb2b60
|
|||
428174271d
|
|||
16813d67ab
|
|||
f3e07290e3
|
|||
87d2781a0e
|
228
blog/New-Keyboard!/index.html
Normal file
228
blog/New-Keyboard!/index.html
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html lang="en">
|
||||||
|
<title>'New Keyboard!'</title>
|
||||||
|
<meta name="date" content="2025/08/12">
|
||||||
|
<link rel="stylesheet" href="/style.css">
|
||||||
|
<style>
|
||||||
|
img { width: 100%; }
|
||||||
|
pre { color: white; }
|
||||||
|
</style>
|
||||||
|
<body id="blog">
|
||||||
|
<h1>New Keyboard!</h1>
|
||||||
|
<a href="#fine_here_it_is">tl;dr show me the board</a>
|
||||||
|
<p>
|
||||||
|
Throughout the past few years I've hopped from keyboard to keyboard
|
||||||
|
initally as a need for something to type on, but eventually as an obession
|
||||||
|
with the sound and feel which to this day I cannot shake.
|
||||||
|
</p>
|
||||||
|
<h2>Keyboard #1</h2>
|
||||||
|
<p>
|
||||||
|
I started on a Razer Cynosa Chroma which as far as I can tell is no longer
|
||||||
|
for sale. But for the sake of context you should know that it's a 100%
|
||||||
|
membrane keyboard with per key backlighting. For a starter keyboard it was
|
||||||
|
fine, but looking back any old office keyboard would've worked and the
|
||||||
|
$40(?) that I spent on it was not worth it. But who cares, lets go to the
|
||||||
|
next keyboard!
|
||||||
|
</p>
|
||||||
|
<h2>Keyboard #2</h2>
|
||||||
|
<p>
|
||||||
|
After being pushed by a friend who was <s>obsessed</s> interested in
|
||||||
|
keyboards I finally took the plunge and built my first custom keyboard.
|
||||||
|
This keyboard was a what I thought would be best after using a membrane
|
||||||
|
for over two years (I had very little clue what I was doing). I ended up
|
||||||
|
choosing a TKL board called the NINJA87BT which came with gateron milky
|
||||||
|
yellow switches. This may not sound custom, but then I went and ordered
|
||||||
|
some very very expensive switches called Helios v2s which are very quiet
|
||||||
|
and so soft to type on. I also bought some keycaps with legends printed
|
||||||
|
on the side nothing too expensive, but very nice to look at. Because this
|
||||||
|
was my first board I had no clue what I was doing and I ended up spending
|
||||||
|
around $300...
|
||||||
|
</p>
|
||||||
|
<h2>Keyboard #3</h2>
|
||||||
|
<p>
|
||||||
|
I started thinking about the future and how I really needed to take care
|
||||||
|
of the hands that I use every day for programming. Though I wanted to go
|
||||||
|
fully ergonomic, like where I'm at now, I chose to pace myself and decided
|
||||||
|
to go with a UHK 60v2. It was expensive, but it promised something
|
||||||
|
spectacular: a split keyboard without the ortho keywells and qmk
|
||||||
|
configuration of my current keyboard which would've been very hard to
|
||||||
|
switch to coming from a normal TKL. Instead of sticking with the cherry
|
||||||
|
reds it came with I put my Helios in (because they are still the best
|
||||||
|
switches I've ever felt). While this board was not nearly as custom as my
|
||||||
|
last I was able to enjoy it much more knowing I was not going to get
|
||||||
|
carpel tunnel halfway through my life.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
I ended up using this board for about a year and a half until around mid
|
||||||
|
July of 2025 when I updated the firmware for the first time since getting
|
||||||
|
the board and it caused the keyboard to start crashing every once in a
|
||||||
|
while. I tried to roll back to the version I was using before, but my
|
||||||
|
configuration wasn't able to migrate back. So I decided it was time to
|
||||||
|
move on to the keyboard I'd been dreaming of making.
|
||||||
|
</p>
|
||||||
|
<h2>Keyboard #4 (my current one)</h2>
|
||||||
|
<p>
|
||||||
|
The keyboard I've been typing this post on is a dactyl manuform 4x5, and
|
||||||
|
It's my first truly hand built keyboard. I 3d printed the case, sanded,
|
||||||
|
primed, painted (although it did not hide the layer lines very well), and
|
||||||
|
wired. Wiring was a bit tricky but thanks to the pictures in the
|
||||||
|
<a href="https://github.com/abstracthat/dactyl-manuform">github repo</a>
|
||||||
|
I was able to do it without too much trouble.
|
||||||
|
</p>
|
||||||
|
<img src="/blog/New-Keyboard!/pics/sanded.jpg">
|
||||||
|
<img src="/blog/New-Keyboard!/pics/wiring.jpg">
|
||||||
|
<p>
|
||||||
|
After finishing the wiring, which took around 12 hours, I tried to flash
|
||||||
|
qmk to both halves. At which point realized that the right half had the
|
||||||
|
rows wired to the arduino pro micro in reverse order. After fixing the
|
||||||
|
slight hiccup I flashed and viola a working keyboard. I then put on some
|
||||||
|
black legend-less keycaps, and here is the final(ish) result:
|
||||||
|
</p>
|
||||||
|
<img id="fine_here_it_is" src="/blog/New-Keyboard!/pics/final-ish.jpg">
|
||||||
|
<p>
|
||||||
|
The ish in final(ish) is because I've yet to add a baseplate which would
|
||||||
|
add some much needed weight so the halves doesn't slide across my desk,
|
||||||
|
but for now I'm happy with it.
|
||||||
|
</p>
|
||||||
|
<h3>Build your own</h3>
|
||||||
|
<p>
|
||||||
|
Incase you're reading this in the hopes of some tips for building your
|
||||||
|
own here they are:
|
||||||
|
<ul>
|
||||||
|
<li>get the model for the keyboard from
|
||||||
|
<a href="https://ryanis.cool/dactyl/#manuform">ryanis.cool/dactyl/#manuform</a></li>
|
||||||
|
<li>when wiring your keyboard try and make the wires going from the
|
||||||
|
rows/columns around 1.5-2x longer than they need to be that way you
|
||||||
|
don't snap when you're fiddling around in there</li>
|
||||||
|
<li>if you want to get rid of layer lines look into acetone dipping your
|
||||||
|
print, I only learned about this after showing my fully wired board
|
||||||
|
to a friend otherwise I would've done it</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
When it comes to using my keyboard it's setup for typing as that's what I
|
||||||
|
do on it it most of the time, however when I play games things get a bit
|
||||||
|
tricky. For games where I can remap the keys I shift every key over by one
|
||||||
|
except for the keys on the bottom row, and then I set the sprint key as a.
|
||||||
|
For the games where I can't remap the keys... I just stop playing them.
|
||||||
|
If I had more of an interest in gaming I would've gone with the 4x6 as
|
||||||
|
6 more keys it offeres could've been really nice.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
For those curious about the specs: I decided on a rj9 port mainly because
|
||||||
|
I like the look of them over the TRRS cables everyone seems to be using
|
||||||
|
nowadays. For the pro micro I went with the cheapest one I could find
|
||||||
|
with a usb-c port, you can't really go wrong here. As for the actual
|
||||||
|
layout my qmk config is below incase you really wanna know how I type:
|
||||||
|
</p>
|
||||||
|
<pre>
|
||||||
|
/*
|
||||||
|
This is the c configuration file for the keymap
|
||||||
|
|
||||||
|
Copyright 2012 Jun Wako <wakojun@gmail.com>
|
||||||
|
Copyright 2015 Jack Humbert
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include QMK_KEYBOARD_H
|
||||||
|
|
||||||
|
bool process_record_user(uint16_t keycode, keyrecord_t* record) {
|
||||||
|
switch (keycode) {
|
||||||
|
case KC_BSPC: {
|
||||||
|
static uint16_t registered_key = KC_NO;
|
||||||
|
if (record->event.pressed) { // On key press.
|
||||||
|
const uint8_t mods = get_mods();
|
||||||
|
#ifndef NO_ACTION_ONESHOT
|
||||||
|
uint8_t shift_mods = (mods | get_oneshot_mods()) & MOD_MASK_SHIFT;
|
||||||
|
#else
|
||||||
|
uint8_t shift_mods = mods & MOD_MASK_SHIFT;
|
||||||
|
#endif // NO_ACTION_ONESHOT
|
||||||
|
if (shift_mods) { // At least one shift key is held.
|
||||||
|
registered_key = KC_DEL;
|
||||||
|
// If one shift is held, clear it from the mods. But if both
|
||||||
|
// shifts are held, leave as is to send Shift + Del.
|
||||||
|
if (shift_mods != MOD_MASK_SHIFT) {
|
||||||
|
#ifndef NO_ACTION_ONESHOT
|
||||||
|
del_oneshot_mods(MOD_MASK_SHIFT);
|
||||||
|
#endif // NO_ACTION_ONESHOT
|
||||||
|
unregister_mods(MOD_MASK_SHIFT);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
registered_key = KC_BSPC;
|
||||||
|
}
|
||||||
|
|
||||||
|
register_code(registered_key);
|
||||||
|
set_mods(mods);
|
||||||
|
} else { // On key release.
|
||||||
|
unregister_code(registered_key);
|
||||||
|
}
|
||||||
|
} return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _BASE 0
|
||||||
|
#define _RAISE 1
|
||||||
|
#define _LOWER 2
|
||||||
|
|
||||||
|
#define SFT_ESC SFT_T(KC_ESC)
|
||||||
|
#define CTL_BSPC CTL_T(KC_BSPC)
|
||||||
|
#define ALT_SPC ALT_T(KC_SPC)
|
||||||
|
#define SFT_ENT SFT_T(KC_ENT)
|
||||||
|
|
||||||
|
#define KC_ML KC_MS_LEFT
|
||||||
|
#define KC_MR KC_MS_RIGHT
|
||||||
|
#define KC_MU KC_MS_UP
|
||||||
|
#define KC_MD KC_MS_DOWN
|
||||||
|
#define KC_MB1 KC_MS_BTN1
|
||||||
|
#define KC_MB2 KC_MS_BTN2
|
||||||
|
|
||||||
|
#define RAISE MO(_RAISE)
|
||||||
|
#define LOWER MO(_LOWER)
|
||||||
|
|
||||||
|
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
|
[_BASE] = LAYOUT(
|
||||||
|
KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P,
|
||||||
|
KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN,
|
||||||
|
KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_QUOT,
|
||||||
|
KC_LBRC, KC_RBRC, KC_MINS, KC_EQL,
|
||||||
|
KC_LCTL, KC_LSFT, KC_TAB, RSFT_T(KC_ESC),
|
||||||
|
KC_SPC, KC_LALT, KC_ENT, KC_BSPC,
|
||||||
|
LOWER, KC_LGUI, KC_RGUI, RAISE
|
||||||
|
),
|
||||||
|
|
||||||
|
[_RAISE] = LAYOUT(
|
||||||
|
QK_BOOT, KC_MPRV, KC_MSTP, KC_MPLY, KC_MNXT, KC_PGDN, MS_BTN1, MS_BTN2, KC_PGUP, KC_VOLU,
|
||||||
|
_______, MS_LEFT, MS_DOWN, MS_UP, MS_RGHT, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, KC_MUTE,
|
||||||
|
_______, MS_WHLL, MS_WHLD, MS_WHLU, MS_WHLR, KC_BSLS, KC_SLSH, KC_LBRC, KC_RBRC, KC_VOLD,
|
||||||
|
_______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______
|
||||||
|
),
|
||||||
|
|
||||||
|
[_LOWER] = LAYOUT(
|
||||||
|
KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN,
|
||||||
|
KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0,
|
||||||
|
KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10,
|
||||||
|
KC_F11, KC_F12, KC_GRV, _______,
|
||||||
|
_______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______
|
||||||
|
)
|
||||||
|
};
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
BIN
blog/New-Keyboard!/pics/final-ish.jpg
Normal file
BIN
blog/New-Keyboard!/pics/final-ish.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 245 KiB |
BIN
blog/New-Keyboard!/pics/sanded.jpg
Normal file
BIN
blog/New-Keyboard!/pics/sanded.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 233 KiB |
BIN
blog/New-Keyboard!/pics/wiring.jpg
Normal file
BIN
blog/New-Keyboard!/pics/wiring.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 406 KiB |
280
blog/Serializing-data-in-C/index.html
Normal file
280
blog/Serializing-data-in-C/index.html
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html lang="en">
|
||||||
|
<title>'Serializing data in C'</title>
|
||||||
|
<meta name="date" content="2025/08/09">
|
||||||
|
<meta name="colorscheme" content="mellow"></meta>
|
||||||
|
<link rel="stylesheet" href="/style.css">
|
||||||
|
<style>
|
||||||
|
.-spell {}
|
||||||
|
.Number {color: #e29eca}
|
||||||
|
.Function {color: #c1c0d4}
|
||||||
|
.String {color: #90b99f}
|
||||||
|
.Character {color: #90b99f}
|
||||||
|
.PreCondit {color: #ea83a5}
|
||||||
|
.-property {color: #c1c0d4}
|
||||||
|
.Comment {color: #757581; font-style: italic}
|
||||||
|
.Macro {color: #ea83a5}
|
||||||
|
.-type-builtin {color: #e29eca}
|
||||||
|
.Type {color: #b9aeda}
|
||||||
|
.Keyword {color: #aca1cf}
|
||||||
|
.Constant {color: #ea83a5}
|
||||||
|
.-variable-parameter {color: #e29eca}
|
||||||
|
.-punctuation-delimiter {color: #9998a8}
|
||||||
|
.-punctuation-bracket {color: #9998a8}
|
||||||
|
.Include {color: #aca1cf}
|
||||||
|
.Structure {color: #e6b99d}
|
||||||
|
.-variable {color: #c9c7cd}
|
||||||
|
.Operator {color: #e6b99d}
|
||||||
|
</style>
|
||||||
|
<body id="blog">
|
||||||
|
<h1>Serializing data in C</h1>
|
||||||
|
<p>
|
||||||
|
I've started work on a new project! The project in question is one that
|
||||||
|
I have wanted to tackle for a long time but did not have the courage to
|
||||||
|
do so. However at long last it is time...
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
time to get funky...
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
I'm writing a music player, and not one that simply plays music like
|
||||||
|
spotify. This music player falls more inline with MPD in which it's a
|
||||||
|
daemon running in the background playing the music and clients may
|
||||||
|
communicate with it to tell it what to play when and the likes.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Currently I'm at that very important part in which the daemon needs to
|
||||||
|
communicate to clients via a protocol *fancy*, and to do so I have decided
|
||||||
|
to go with a socket that way <i>in theory</i> I can control my daemon from
|
||||||
|
other devices on the network. With the communication method decided I now
|
||||||
|
have to define what data goes between devices. At the current moment I've
|
||||||
|
settled on an enum for different signals.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
As seen here:
|
||||||
|
</p>
|
||||||
|
<pre>
|
||||||
|
<span class="Structure"><span class="Keyword">enum</span></span> <span class="Type">libmoo_signal</span> <span class="-punctuation-bracket">{</span>
|
||||||
|
<span class="Comment"><span class="Comment"><span class="-spell">/* core signals are in the < 100 range */</span></span></span>
|
||||||
|
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_ESTCON</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">1</span></span><span class="-punctuation-delimiter">,</span>
|
||||||
|
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_ESTDCON</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">2</span></span><span class="-punctuation-delimiter">,</span>
|
||||||
|
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_INCOMPATABLE_VERSION</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">3</span></span><span class="-punctuation-delimiter">,</span>
|
||||||
|
|
||||||
|
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_OK</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">50</span></span><span class="-punctuation-delimiter">,</span> <span class="Comment"><span class="Comment"><span class="-spell">/* previous message received was ok */</span></span></span>
|
||||||
|
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_NOK</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">51</span></span><span class="-punctuation-delimiter">,</span> <span class="Comment"><span class="Comment"><span class="-spell">/* previous message received was not ok */</span></span></span>
|
||||||
|
|
||||||
|
<span class="Comment"><span class="Comment"><span class="-spell">/* setting/adding data happens in the 100 range */</span></span></span>
|
||||||
|
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_ADD_SONG</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">101</span></span><span class="-punctuation-delimiter">,</span>
|
||||||
|
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_SET_PLAY</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">103</span></span><span class="-punctuation-delimiter">,</span>
|
||||||
|
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_SET_PAUSE</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">104</span></span><span class="-punctuation-delimiter">,</span>
|
||||||
|
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_SET_TOGGLE_PAUSE</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">105</span></span><span class="-punctuation-delimiter">,</span>
|
||||||
|
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_SET_SKIP_NEXT</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">110</span></span><span class="-punctuation-delimiter">,</span>
|
||||||
|
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_SET_SKIP_PREV</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">111</span></span><span class="-punctuation-delimiter">,</span>
|
||||||
|
|
||||||
|
<span class="Comment"><span class="Comment"><span class="-spell">/* removing data happens in the 200 range */</span></span></span>
|
||||||
|
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_REM_SONG</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">201</span></span><span class="-punctuation-delimiter">,</span>
|
||||||
|
|
||||||
|
<span class="Comment"><span class="Comment"><span class="-spell">/* getting data happens in the 300 range */</span></span></span>
|
||||||
|
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_GET_CUR_SONG</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">301</span></span><span class="-punctuation-delimiter">,</span>
|
||||||
|
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_GET_PAUSE</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">303</span></span><span class="-punctuation-delimiter">,</span>
|
||||||
|
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_GET_PROGRESS</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">310</span></span><span class="-punctuation-delimiter">,</span>
|
||||||
|
<span class="-punctuation-bracket">}</span><span class="-punctuation-delimiter">;</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
As for how I actually transmit the signals, I've settled on a format which
|
||||||
|
defaults to 42 bytes of data being sent with the option to send more by
|
||||||
|
setting the 41st-42nd bytes to a uint16 containing the additional number
|
||||||
|
of bytes being sent.
|
||||||
|
</p>
|
||||||
|
<pre>
|
||||||
|
<span class="Comment"><span class="Comment"><span class="-spell">/* byte - data</span></span><span class="-spell">
|
||||||
|
<span class="Comment"> *</span>
|
||||||
|
<span class="Comment"> * 0-7 - libmoo protocol version</span>
|
||||||
|
<span class="Comment"> *</span>
|
||||||
|
<span class="Comment"> * 8-31 - reserved for the future</span>
|
||||||
|
<span class="Comment"> *</span>
|
||||||
|
<span class="Comment"> * 32-40 - libmoo_signal</span>
|
||||||
|
<span class="Comment"> *</span>
|
||||||
|
<span class="Comment"> * 41-42 - uint16 more_data</span>
|
||||||
|
<span class="Comment"> *</span>
|
||||||
|
<span class="Comment"> * 43-8191 - char *data</span>
|
||||||
|
<span class="Comment"> */</span></span><span class="Comment"></span></span>
|
||||||
|
<span class="Structure"><span class="Keyword">typedef</span></span> <span class="Type"><span class="-type-builtin">char</span></span> <span class="Operator">*</span> <span class="Type">libmoo_payload</span><span class="-punctuation-delimiter">;</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
I'm not sure how this compares to other protocols used to transmit data,
|
||||||
|
but I'm quite proud of how I've laid this out.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Moving on to actual the point of this article: serialization. For the sake
|
||||||
|
of useablilty I've defined a datatype which models our payload which you
|
||||||
|
can see here:
|
||||||
|
</p>
|
||||||
|
<pre>
|
||||||
|
<span class="Structure"><span class="Keyword">typedef</span></span> <span class="Structure"><span class="Keyword">struct</span></span> <span class="-punctuation-bracket">{</span>
|
||||||
|
<span class="Structure"><span class="Keyword">enum</span></span> <span class="Type">libmoo_signal</span> <span class="-property">signal</span><span class="-punctuation-delimiter">;</span> <span class="Comment"><span class="Comment"><span class="-spell">/* the signal */</span></span></span>
|
||||||
|
<span class="Type"><span class="-type-builtin">uint16_t</span></span> <span class="-property">more_data</span><span class="-punctuation-delimiter">;</span> <span class="Comment"><span class="Comment"><span class="-spell">/* the number bytes of the additional data */</span></span></span>
|
||||||
|
<span class="Type"><span class="-type-builtin">char</span></span> <span class="Operator">*</span><span class="-property">data</span><span class="-punctuation-delimiter">;</span> <span class="Comment"><span class="Comment"><span class="-spell">/* additional data */</span></span></span>
|
||||||
|
<span class="-punctuation-bracket">}</span> <span class="Type"><span class="Type">libmoo_data</span></span><span class="-punctuation-delimiter">;</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
And a function which allows you to easily create libmoo_data:
|
||||||
|
</p>
|
||||||
|
<pre>
|
||||||
|
<span class="Comment"><span class="Comment"><span class="-spell"><span class="Comment">/**</span>
|
||||||
|
<span class="Comment"> * @brief create a new libmoo_data</span>
|
||||||
|
<span class="Comment"> *</span>
|
||||||
|
<span class="Comment"> * @param signal the signal to set</span>
|
||||||
|
<span class="Comment"> * @param data the data to set</span>
|
||||||
|
<span class="Comment"> * @return the data object</span>
|
||||||
|
<span class="Comment"> */</span></span></span></span>
|
||||||
|
<span class="Type">libmoo_data</span> <span class="Operator">*</span><span class="-variable"><span class="Function">libmoo_create_data</span></span><span class="-punctuation-bracket">(</span><span class="Structure"><span class="Keyword">enum</span></span> <span class="Type">libmoo_signal</span> <span class="-variable"><span class="-variable-parameter">signal</span></span><span class="-punctuation-delimiter">,</span> <span class="Type"><span class="-type-builtin">char</span></span> <span class="-variable-parameter"><span class="Operator">*</span><span class="-variable">data</span></span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
I've provided this so that you don't have to deal with manually setting
|
||||||
|
the size of the data that you pass into the object, although (if you so
|
||||||
|
choose) you may easily override it.
|
||||||
|
</p>
|
||||||
|
<h2>Serializing</h2>
|
||||||
|
<p>
|
||||||
|
Now that we've gone over the interface for interacting with the payload
|
||||||
|
let's get to the intersting stage in which we get the data ready for
|
||||||
|
launch.
|
||||||
|
</p>
|
||||||
|
<pre>
|
||||||
|
<span class="Comment"><span class="Comment"><span class="-spell"><span class="Comment">/**</span>
|
||||||
|
<span class="Comment"> * @brief convert data into a payload.</span>
|
||||||
|
<span class="Comment"> * The payload must be allocated prior to calling this function it should be</span>
|
||||||
|
<span class="Comment"> * LIBMOO_PAYLOAD_SIZE chars long unless you think you know better.</span>
|
||||||
|
<span class="Comment"> *</span>
|
||||||
|
<span class="Comment"> * @param payload pointer to the payload</span>
|
||||||
|
<span class="Comment"> * @param data data which will be serialized</span>
|
||||||
|
<span class="Comment"> * @return the size of the resulting payload</span>
|
||||||
|
<span class="Comment"> */</span></span></span></span>
|
||||||
|
<span class="Type"><span class="-type-builtin">size_t</span></span>
|
||||||
|
<span class="-variable"><span class="Function">libmoo_serialize_data</span></span><span class="-punctuation-bracket">(</span><span class="Type">libmoo_payload</span> <span class="-variable"><span class="-variable-parameter">payload</span></span><span class="-punctuation-delimiter">,</span> <span class="Type">libmoo_data</span> <span class="-variable-parameter"><span class="Operator">*</span><span class="-variable">data</span></span><span class="-punctuation-bracket">)</span>
|
||||||
|
<span class="-punctuation-bracket">{</span>
|
||||||
|
<span class="Type"><span class="-type-builtin">void</span></span> <span class="Operator">*</span><span class="-variable">ptr</span><span class="-punctuation-delimiter">;</span>
|
||||||
|
|
||||||
|
<span class="-variable">ptr</span> <span class="Operator">=</span> <span class="-variable">payload</span><span class="-punctuation-delimiter">;</span>
|
||||||
|
|
||||||
|
<span class="Comment"><span class="Comment"><span class="-spell">/* add LIBMOO_VERSION */</span></span></span>
|
||||||
|
<span class="-variable"><span class="Function">mempcpy</span></span><span class="-punctuation-bracket">(</span><span class="-variable">ptr</span><span class="-punctuation-delimiter">,</span> <span class="-variable"><span class="Constant">LIBMOO_VERSION</span></span><span class="-punctuation-delimiter">,</span> <span class="-variable"><span class="Function">strlen</span></span><span class="-punctuation-bracket">(</span><span class="-variable"><span class="Constant">LIBMOO_VERSION</span></span><span class="-punctuation-bracket">)</span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
|
||||||
|
|
||||||
|
<span class="Comment"><span class="Comment"><span class="-spell">/* skip the reserved space */</span></span></span>
|
||||||
|
<span class="-variable">ptr</span> <span class="Operator">+=</span> <span class="Number"><span class="Number">24</span></span><span class="-punctuation-delimiter">;</span>
|
||||||
|
|
||||||
|
<span class="Comment"><span class="Comment"><span class="-spell">/* add the signal type */</span></span></span>
|
||||||
|
<span class="-variable"><span class="Function">mempcpy</span></span><span class="-punctuation-bracket">(</span><span class="-variable">ptr</span><span class="-punctuation-delimiter">,</span> <span class="Operator">&</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-></span><span class="-property">signal</span></span><span class="-punctuation-delimiter">,</span> <span class="Operator"><span class="Keyword">sizeof</span></span><span class="-punctuation-bracket">(</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-></span><span class="-property">signal</span></span><span class="-punctuation-bracket">)</span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
|
||||||
|
|
||||||
|
<span class="Comment"><span class="Comment"><span class="-spell">/* add the size of the more data */</span></span></span>
|
||||||
|
<span class="-variable"><span class="Function">mempcpy</span></span><span class="-punctuation-bracket">(</span><span class="-variable">ptr</span><span class="-punctuation-delimiter">,</span> <span class="Operator">&</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-></span><span class="-property">more_data</span></span><span class="-punctuation-delimiter">,</span> <span class="Operator"><span class="Keyword">sizeof</span></span><span class="-punctuation-bracket">(</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-></span><span class="-property">more_data</span></span><span class="-punctuation-bracket">)</span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
|
||||||
|
|
||||||
|
<span class="Comment"><span class="Comment"><span class="-spell">/* the more data */</span></span></span>
|
||||||
|
<span class="Conditional"><span class="Keyword">if</span></span> <span class="-punctuation-bracket">(</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-></span><span class="-property">more_data</span></span><span class="-punctuation-bracket">)</span> <span class="-punctuation-bracket">{</span>
|
||||||
|
<span class="-variable"><span class="Function">mempcpy</span></span><span class="-punctuation-bracket">(</span><span class="-variable">ptr</span><span class="-punctuation-delimiter">,</span> <span class="-_parent"><span class="-variable">data</span><span class="Operator">-></span><span class="-property">data</span></span><span class="-punctuation-delimiter">,</span> <span class="-variable"><span class="Function">strlen</span></span><span class="-punctuation-bracket">(</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-></span><span class="-property">data</span></span><span class="-punctuation-bracket">)</span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
|
||||||
|
<span class="-punctuation-bracket">}</span>
|
||||||
|
|
||||||
|
<span class="Statement"><span class="Keyword">return</span></span> <span class="-variable"><span class="Constant">LIBMOO_HEADER_SIZE</span></span> <span class="Operator">+</span> <span class="Operator"><span class="Keyword">sizeof</span></span><span class="-punctuation-bracket">(</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-></span><span class="-property">more_data</span></span><span class="-punctuation-bracket">)</span> <span class="Operator">+</span> <span class="-_parent"><span class="-variable">data</span><span class="Operator">-></span><span class="-property">more_data</span></span><span class="-punctuation-delimiter">;</span>
|
||||||
|
<span class="-punctuation-bracket">}</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
As you may have noticed in the code snippet above libmoo_serialize_data is
|
||||||
|
a function that takes in a pre-allocated payload, and the data to
|
||||||
|
serialize. I've opted to allow the user to allocate space for the payload
|
||||||
|
if they determine that they know what they're doing incase my dumb
|
||||||
|
function is too generous. Moving onto the body of the function you'll see
|
||||||
|
an unfamiliar function called mempcpy which is a macro for copying data
|
||||||
|
into the payload. This macro takes in the same arguments as memcpy (dest,
|
||||||
|
src, size), but in addition it increments dest by size so I can append
|
||||||
|
data to the payload without making this code horrible to read.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
In earlier stages of development I didn't actually return the size of the
|
||||||
|
resulting payload, thinking that I could just strlen it. This was a rookie
|
||||||
|
mistake. Because I've included extra space (bytes 8-31) when you run
|
||||||
|
strlen on any payload it results in 5 (the length of the version string).
|
||||||
|
After finding this out I decided that I do actually want to send more
|
||||||
|
than the version information, and so now libmoo_serialize_data returns a
|
||||||
|
size_t continaing the number of bytes that have been serialized.
|
||||||
|
</p>
|
||||||
|
<h2>Deserializing</h2>
|
||||||
|
<p>
|
||||||
|
Now that we've serialized and <i>presumably</i> sent the data to a client
|
||||||
|
we need to do the magic part which completes this transaction:
|
||||||
|
deserialization.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Below is my method of deserializing the data. It's pretty much the
|
||||||
|
opposite of the serialization function with the key exception that we
|
||||||
|
need to do some validation. <i>Which I haven't implemented yet.</i>
|
||||||
|
</p>
|
||||||
|
<pre>
|
||||||
|
<span class="Type">libmoo_data</span>
|
||||||
|
<span class="Operator">*</span><span class="-variable"><span class="Function">libmoo_deserialize_data</span></span><span class="-punctuation-bracket">(</span><span class="Type">libmoo_payload</span> <span class="-variable"><span class="-variable-parameter">payload</span></span><span class="-punctuation-delimiter">,</span> <span class="Type"><span class="-type-builtin">unsigned</span></span> <span class="Type"><span class="-type-builtin"><span class="-type-builtin">int</span></span></span> <span class="-variable"><span class="-variable-parameter">payload_size</span></span><span class="-punctuation-bracket">)</span>
|
||||||
|
<span class="-punctuation-bracket">{</span>
|
||||||
|
<span class="Type">libmoo_data</span> <span class="Operator">*</span><span class="-variable">data</span><span class="-punctuation-delimiter">;</span>
|
||||||
|
<span class="Type"><span class="-type-builtin">char</span></span> <span class="-variable">libmoo_version</span><span class="-punctuation-bracket">[</span><span class="-variable"><span class="Constant">LIBMOO_VERSION_LEN</span></span> <span class="Operator">+</span> <span class="Number"><span class="Number">1</span></span><span class="-punctuation-bracket">]</span><span class="-punctuation-delimiter">;</span>
|
||||||
|
|
||||||
|
<span class="Comment"><span class="Comment"><span class="-spell">/* ensure that there's enough data to comply to spec */</span></span></span>
|
||||||
|
<span class="Conditional"><span class="Keyword">if</span></span> <span class="-punctuation-bracket">(</span><span class="-variable">payload_size</span> <span class="Operator"><</span> <span class="-variable"><span class="Constant">LIBMOO_HEADER_SIZE</span></span><span class="-punctuation-bracket">)</span> <span class="-punctuation-bracket">{</span>
|
||||||
|
<span class="-variable">errno</span> <span class="Operator">=</span> <span class="-variable"><span class="Constant">EBADE</span></span><span class="-punctuation-delimiter">;</span>
|
||||||
|
<span class="Statement"><span class="Keyword">return</span></span> <span class="Constant"><span class="-constant-builtin">NULL</span></span><span class="-punctuation-delimiter">;</span>
|
||||||
|
<span class="-punctuation-bracket">}</span>
|
||||||
|
|
||||||
|
<span class="Comment"><span class="Comment"><span class="-spell">/* attempt to allocate space and if we fail return NULL errno contains the</span></span><span class="-spell">
|
||||||
|
<span class="Comment"> * error</span>
|
||||||
|
<span class="Comment"> */</span></span><span class="Comment"></span></span>
|
||||||
|
<span class="-variable">data</span> <span class="Operator">=</span> <span class="-variable"><span class="Function">calloc</span></span><span class="-punctuation-bracket">(</span><span class="Number"><span class="Number">1</span></span><span class="-punctuation-delimiter">,</span> <span class="Operator"><span class="Keyword">sizeof</span></span><span class="-punctuation-bracket">(</span><span class="-variable">libmoo_data</span><span class="-punctuation-bracket">)</span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
|
||||||
|
<span class="Conditional"><span class="Keyword">if</span></span> <span class="-punctuation-bracket">(</span><span class="-variable">data</span> <span class="Operator">==</span> <span class="Constant"><span class="-constant-builtin">NULL</span></span><span class="-punctuation-bracket">)</span> <span class="-punctuation-bracket">{</span>
|
||||||
|
<span class="-variable">errno</span> <span class="Operator">=</span> <span class="Constant"><span class="-variable"><span class="Constant">ENOMEM</span></span></span><span class="-punctuation-delimiter">;</span>
|
||||||
|
<span class="Statement"><span class="Keyword">return</span></span> <span class="Constant"><span class="-constant-builtin">NULL</span></span><span class="-punctuation-delimiter">;</span>
|
||||||
|
<span class="-punctuation-bracket">}</span>
|
||||||
|
|
||||||
|
<span class="Comment"><span class="Comment"><span class="-spell">/* get the libmoo_version */</span></span></span>
|
||||||
|
<span class="-variable"><span class="Function">memscpy</span></span><span class="-punctuation-bracket">(</span><span class="-variable">libmoo_version</span><span class="-punctuation-delimiter">,</span> <span class="-variable">payload</span><span class="-punctuation-delimiter">,</span> <span class="-variable"><span class="Constant">LIBMOO_VERSION_LEN</span></span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
|
||||||
|
<span class="-variable">libmoo_version</span><span class="-punctuation-bracket">[</span><span class="-variable"><span class="Constant">LIBMOO_VERSION_LEN</span></span><span class="-punctuation-bracket">]</span> <span class="Operator">=</span> <span class="SpecialChar"><span class="Character">'<span class="-string-escape">\0</span>'</span></span><span class="-punctuation-delimiter">;</span>
|
||||||
|
|
||||||
|
<span class="Comment"><span class="Comment"><span class="-spell">/*<span class="TodoBgNOTE"> </span></span></span><span class="-spell"><span class="TodoBgNOTE"><span class="Todo">TODO</span><span class="Comment"><span class="TodoFgNOTE">:</span></span></span><span class="Comment"><span class="TodoFgNOTE"> check that the version of the library we're talking to and our</span></span>
|
||||||
|
<span class="Comment"> * <span class="TodoFgNOTE">version are compatable</span></span>
|
||||||
|
<span class="Comment"> */</span></span><span class="Comment"></span></span>
|
||||||
|
|
||||||
|
<span class="Comment"><span class="Comment"><span class="-spell">/* gotta tell the client that we're incompatible */</span></span></span>
|
||||||
|
<span class="Conditional"><span class="Keyword">if</span></span> <span class="-punctuation-bracket">(</span><span class="-variable"><span class="Function">strcmp</span></span><span class="-punctuation-bracket">(</span><span class="-variable">libmoo_version</span><span class="-punctuation-delimiter">,</span> <span class="-variable"><span class="Constant">LIBMOO_VERSION</span></span><span class="-punctuation-bracket">)</span> <span class="Operator">!=</span> <span class="Number"><span class="Number">0</span></span><span class="-punctuation-bracket">)</span> <span class="-punctuation-bracket">{</span>
|
||||||
|
<span class="-variable">errno</span> <span class="Operator">=</span> <span class="Constant"><span class="-variable"><span class="Constant">EINVAL</span></span></span><span class="-punctuation-delimiter">;</span>
|
||||||
|
<span class="-variable"><span class="Function">free</span></span><span class="-punctuation-bracket">(</span><span class="-variable">data</span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
|
||||||
|
<span class="Statement"><span class="Keyword">return</span></span> <span class="Constant"><span class="-constant-builtin">NULL</span></span><span class="-punctuation-delimiter">;</span>
|
||||||
|
<span class="-punctuation-bracket">}</span>
|
||||||
|
|
||||||
|
<span class="Comment"><span class="Comment"><span class="-spell">/* skip the reserved space */</span></span></span>
|
||||||
|
<span class="-variable">payload</span> <span class="Operator">+=</span> <span class="Number"><span class="Number">24</span></span><span class="-punctuation-delimiter">;</span>
|
||||||
|
|
||||||
|
<span class="Comment"><span class="Comment"><span class="-spell">/* get the signal */</span></span></span>
|
||||||
|
<span class="-variable"><span class="Function">memscpy</span></span><span class="-punctuation-bracket">(</span><span class="Operator">&</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-></span><span class="-property">signal</span></span><span class="-punctuation-delimiter">,</span> <span class="-variable">payload</span><span class="-punctuation-delimiter">,</span> <span class="Operator"><span class="Keyword">sizeof</span></span><span class="-punctuation-bracket">(</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-></span><span class="-property">signal</span></span><span class="-punctuation-bracket">)</span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
|
||||||
|
|
||||||
|
<span class="Comment"><span class="Comment"><span class="-spell">/* get the more data marker */</span></span></span>
|
||||||
|
<span class="-variable"><span class="Function">memscpy</span></span><span class="-punctuation-bracket">(</span><span class="Operator">&</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-></span><span class="-property">more_data</span></span><span class="-punctuation-delimiter">,</span> <span class="-variable">payload</span><span class="-punctuation-delimiter">,</span> <span class="Operator"><span class="Keyword">sizeof</span></span><span class="-punctuation-bracket">(</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-></span><span class="-property">more_data</span></span><span class="-punctuation-bracket">)</span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
|
||||||
|
|
||||||
|
<span class="Comment"><span class="Comment"><span class="-spell">/* get the data */</span></span></span>
|
||||||
|
<span class="Conditional"><span class="Keyword">if</span></span> <span class="-punctuation-bracket">(</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-></span><span class="-property">more_data</span></span><span class="-punctuation-bracket">)</span> <span class="-punctuation-bracket">{</span>
|
||||||
|
<span class="-_parent"><span class="-variable">data</span><span class="Operator">-></span><span class="-property">data</span></span> <span class="Operator">=</span> <span class="-variable"><span class="Function">malloc</span></span><span class="-punctuation-bracket">(</span><span class="-punctuation-bracket">(</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-></span><span class="-property">more_data</span></span> <span class="Operator">+</span> <span class="Number"><span class="Number">1</span></span><span class="-punctuation-bracket">)</span> <span class="Operator">*</span> <span class="Operator"><span class="Keyword">sizeof</span></span><span class="-punctuation-bracket">(</span><span class="Type"><span class="Type"><span class="-type-builtin">char</span></span></span><span class="-punctuation-bracket">)</span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
|
||||||
|
<span class="-variable"><span class="Function">memscpy</span></span><span class="-punctuation-bracket">(</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-></span><span class="-property">data</span></span><span class="-punctuation-delimiter">,</span> <span class="-variable">payload</span><span class="-punctuation-delimiter">,</span> <span class="-_parent"><span class="-variable">data</span><span class="Operator">-></span><span class="-property">more_data</span></span> <span class="Operator">*</span> <span class="Operator"><span class="Keyword">sizeof</span></span><span class="-punctuation-bracket">(</span><span class="Type"><span class="Type"><span class="-type-builtin">char</span></span></span><span class="-punctuation-bracket">)</span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
|
||||||
|
<span class="-_parent"><span class="-variable">data</span><span class="Operator">-></span><span class="-property">data</span></span><span class="-punctuation-bracket">[</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-></span><span class="-property">more_data</span></span><span class="-punctuation-bracket">]</span> <span class="Operator">=</span> <span class="SpecialChar"><span class="Character">'<span class="-string-escape">\0</span>'</span></span><span class="-punctuation-delimiter">;</span> <span class="Comment"><span class="Comment"><span class="-spell">/* null terminate this string, yo */</span></span></span>
|
||||||
|
<span class="-punctuation-bracket">}</span>
|
||||||
|
|
||||||
|
<span class="Statement"><span class="Keyword">return</span></span> <span class="-variable">data</span><span class="-punctuation-delimiter">;</span>
|
||||||
|
<span class="-punctuation-bracket">}</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
And that's kinda it just like with the mempcpy macro I've made a memscpy
|
||||||
|
macro which increments the src by the size of the data to make reading
|
||||||
|
the data easy.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
See you next year o/
|
||||||
|
<sub>I might have my project done by then, who knows</sub>
|
||||||
|
</p>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -1,35 +0,0 @@
|
|||||||
<!DOCTYPE HTML>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<title>Squibid's Blog</title>
|
|
||||||
<link rel="stylesheet" href="/style.css">
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
</head>
|
|
||||||
<style type="text/css">
|
|
||||||
#bloglist {
|
|
||||||
text-align: left;
|
|
||||||
font-size: 2ch;
|
|
||||||
}
|
|
||||||
p#bloglist span {
|
|
||||||
float: right;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<body style="background-color: #161617;">
|
|
||||||
<div id="master">
|
|
||||||
<header>
|
|
||||||
<h1 id="font", style="margin-bottom: 0">
|
|
||||||
<a href="/">Squibid's</a> Blog
|
|
||||||
</h1>
|
|
||||||
</header>
|
|
||||||
<hr style="color: #f7f7f7;">
|
|
||||||
<p id="bloglist">
|
|
||||||
<?php include(__DIR__.'/../misc/tools.php'); blog_entries("../blog"); ?>
|
|
||||||
</p>
|
|
||||||
<h2 id="font" style="text-align: center; margin-top: 0;">
|
|
||||||
<a href="/blog/rss.xml", title="rss">subscribe</a>
|
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
231
blog/rss.xml
231
blog/rss.xml
@ -11,6 +11,237 @@
|
|||||||
|
|
||||||
<!-- LB -->
|
<!-- LB -->
|
||||||
|
|
||||||
|
<item>
|
||||||
|
<title> 'New Keyboard!'</title>
|
||||||
|
<guid>https://squi.bid/blog/New-Keyboard!/index.html</guid>
|
||||||
|
<link>https://squi.bid/blog/New-Keyboard!/index.html</link>
|
||||||
|
<pubDate>Tue, 12 Aug 2025 03:23:38 -0400</pubDate>
|
||||||
|
<description><![CDATA[<!DOCTYPE HTML>
|
||||||
|
<html lang="en">
|
||||||
|
<title>'New Keyboard!'</title>
|
||||||
|
<meta name="date" content="2025/08/12">
|
||||||
|
<link rel="stylesheet" href="/style.css">
|
||||||
|
<style>
|
||||||
|
img { width: 100%; }
|
||||||
|
pre { color: white; }
|
||||||
|
</style>
|
||||||
|
<body id="blog">
|
||||||
|
<h1>New Keyboard!</h1>
|
||||||
|
<a href="#fine_here_it_is">tl;dr show me the board</a>
|
||||||
|
<p>
|
||||||
|
Throughout the past few years I've hopped from keyboard to keyboard
|
||||||
|
initally as a need for something to type on, but eventually as an obession
|
||||||
|
with the sound and feel which to this day I cannot shake.
|
||||||
|
</p>
|
||||||
|
<h2>Keyboard #1</h2>
|
||||||
|
<p>
|
||||||
|
I started on a Razer Cynosa Chroma which as far as I can tell is no longer
|
||||||
|
for sale. But for the sake of context you should know that it's a 100%
|
||||||
|
membrane keyboard with per key backlighting. For a starter keyboard it was
|
||||||
|
fine, but looking back any old office keyboard would've worked and the
|
||||||
|
$40(?) that I spent on it was not worth it. But who cares, lets go to the
|
||||||
|
next keyboard!
|
||||||
|
</p>
|
||||||
|
<h2>Keyboard #2</h2>
|
||||||
|
<p>
|
||||||
|
After being pushed by a friend who was <s>obsessed</s> interested in
|
||||||
|
keyboards I finally took the plunge and built my first custom keyboard.
|
||||||
|
This keyboard was a what I thought would be best after using a membrane
|
||||||
|
for over two years (I had very little clue what I was doing). I ended up
|
||||||
|
choosing a TKL board called the NINJA87BT which came with gateron milky
|
||||||
|
yellow switches. This may not sound custom, but then I went and ordered
|
||||||
|
some very very expensive switches called Helios v2s which are very quiet
|
||||||
|
and so soft to type on. I also bought some keycaps with legends printed
|
||||||
|
on the side nothing too expensive, but very nice to look at. Because this
|
||||||
|
was my first board I had no clue what I was doing and I ended up spending
|
||||||
|
around $300...
|
||||||
|
</p>
|
||||||
|
<h2>Keyboard #3</h2>
|
||||||
|
<p>
|
||||||
|
I started thinking about the future and how I really needed to take care
|
||||||
|
of the hands that I use every day for programming. Though I wanted to go
|
||||||
|
fully ergonomic, like where I'm at now, I chose to pace myself and decided
|
||||||
|
to go with a UHK 60v2. It was expensive, but it promised something
|
||||||
|
spectacular: a split keyboard without the ortho keywells and qmk
|
||||||
|
configuration of my current keyboard which would've been very hard to
|
||||||
|
switch to coming from a normal TKL. Instead of sticking with the cherry
|
||||||
|
reds it came with I put my Helios in (because they are still the best
|
||||||
|
switches I've ever felt). While this board was not nearly as custom as my
|
||||||
|
last I was able to enjoy it much more knowing I was not going to get
|
||||||
|
carpel tunnel halfway through my life.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
I ended up using this board for about a year and a half until around mid
|
||||||
|
July of 2025 when I updated the firmware for the first time since getting
|
||||||
|
the board and it caused the keyboard to start crashing every once in a
|
||||||
|
while. I tried to roll back to the version I was using before, but my
|
||||||
|
configuration wasn't able to migrate back. So I decided it was time to
|
||||||
|
move on to the keyboard I'd been dreaming of making.
|
||||||
|
</p>
|
||||||
|
<h2>Keyboard #4 (my current one)</h2>
|
||||||
|
<p>
|
||||||
|
The keyboard I've been typing this post on is a dactyl manuform 4x5, and
|
||||||
|
It's my first truly hand built keyboard. I 3d printed the case, sanded,
|
||||||
|
primed, painted (although it did not hide the layer lines very well), and
|
||||||
|
wired. Wiring was a bit tricky but thanks to the pictures in the
|
||||||
|
<a href="https://github.com/abstracthat/dactyl-manuform">github repo</a>
|
||||||
|
I was able to do it without too much trouble.
|
||||||
|
</p>
|
||||||
|
<img src="/blog/New-Keyboard!/pics/sanded.jpg">
|
||||||
|
<img src="/blog/New-Keyboard!/pics/wiring.jpg">
|
||||||
|
<p>
|
||||||
|
After finishing the wiring, which took around 12 hours, I tried to flash
|
||||||
|
qmk to both halves. At which point realized that the right half had the
|
||||||
|
rows wired to the arduino pro micro in reverse order. After fixing the
|
||||||
|
slight hiccup I flashed and viola a working keyboard. I then put on some
|
||||||
|
black legend-less keycaps, and here is the final(ish) result:
|
||||||
|
</p>
|
||||||
|
<img id="fine_here_it_is" src="/blog/New-Keyboard!/pics/final-ish.jpg">
|
||||||
|
<p>
|
||||||
|
The ish in final(ish) is because I've yet to add a baseplate which would
|
||||||
|
add some much needed weight so the halves doesn't slide across my desk,
|
||||||
|
but for now I'm happy with it.
|
||||||
|
</p>
|
||||||
|
<h3>Build your own</h3>
|
||||||
|
<p>
|
||||||
|
Incase you're reading this in the hopes of some tips for building your
|
||||||
|
own here they are:
|
||||||
|
<ul>
|
||||||
|
<li>get the model for the keyboard from
|
||||||
|
<a href="https://ryanis.cool/dactyl/#manuform">ryanis.cool/dactyl/#manuform</a></li>
|
||||||
|
<li>when wiring your keyboard try and make the wires going from the
|
||||||
|
rows/columns around 1.5-2x longer than they need to be that way you
|
||||||
|
don't snap when you're fiddling around in there</li>
|
||||||
|
<li>if you want to get rid of layer lines look into acetone dipping your
|
||||||
|
print, I only learned about this after showing my fully wired board
|
||||||
|
to a friend otherwise I would've done it</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
When it comes to using my keyboard it's setup for typing as that's what I
|
||||||
|
do on it it most of the time, however when I play games things get a bit
|
||||||
|
tricky. For games where I can remap the keys I shift every key over by one
|
||||||
|
except for the keys on the bottom row, and then I set the sprint key as a.
|
||||||
|
For the games where I can't remap the keys... I just stop playing them.
|
||||||
|
If I had more of an interest in gaming I would've gone with the 4x6 as
|
||||||
|
6 more keys it offeres could've been really nice.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
For those curious about the specs: I decided on a rj9 port mainly because
|
||||||
|
I like the look of them over the TRRS cables everyone seems to be using
|
||||||
|
nowadays. For the pro micro I went with the cheapest one I could find
|
||||||
|
with a usb-c port, you can't really go wrong here. As for the actual
|
||||||
|
layout my qmk config is below incase you really wanna know how I type:
|
||||||
|
</p>
|
||||||
|
<pre>
|
||||||
|
/*
|
||||||
|
This is the c configuration file for the keymap
|
||||||
|
Copyright 2012 Jun Wako <wakojun@gmail.com>
|
||||||
|
Copyright 2015 Jack Humbert
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include QMK_KEYBOARD_H
|
||||||
|
bool process_record_user(uint16_t keycode, keyrecord_t* record) {
|
||||||
|
switch (keycode) {
|
||||||
|
case KC_BSPC: {
|
||||||
|
static uint16_t registered_key = KC_NO;
|
||||||
|
if (record->event.pressed) { // On key press.
|
||||||
|
const uint8_t mods = get_mods();
|
||||||
|
#ifndef NO_ACTION_ONESHOT
|
||||||
|
uint8_t shift_mods = (mods | get_oneshot_mods()) & MOD_MASK_SHIFT;
|
||||||
|
#else
|
||||||
|
uint8_t shift_mods = mods & MOD_MASK_SHIFT;
|
||||||
|
#endif // NO_ACTION_ONESHOT
|
||||||
|
if (shift_mods) { // At least one shift key is held.
|
||||||
|
registered_key = KC_DEL;
|
||||||
|
// If one shift is held, clear it from the mods. But if both
|
||||||
|
// shifts are held, leave as is to send Shift + Del.
|
||||||
|
if (shift_mods != MOD_MASK_SHIFT) {
|
||||||
|
#ifndef NO_ACTION_ONESHOT
|
||||||
|
del_oneshot_mods(MOD_MASK_SHIFT);
|
||||||
|
#endif // NO_ACTION_ONESHOT
|
||||||
|
unregister_mods(MOD_MASK_SHIFT);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
registered_key = KC_BSPC;
|
||||||
|
}
|
||||||
|
register_code(registered_key);
|
||||||
|
set_mods(mods);
|
||||||
|
} else { // On key release.
|
||||||
|
unregister_code(registered_key);
|
||||||
|
}
|
||||||
|
} return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#define _BASE 0
|
||||||
|
#define _RAISE 1
|
||||||
|
#define _LOWER 2
|
||||||
|
#define SFT_ESC SFT_T(KC_ESC)
|
||||||
|
#define CTL_BSPC CTL_T(KC_BSPC)
|
||||||
|
#define ALT_SPC ALT_T(KC_SPC)
|
||||||
|
#define SFT_ENT SFT_T(KC_ENT)
|
||||||
|
#define KC_ML KC_MS_LEFT
|
||||||
|
#define KC_MR KC_MS_RIGHT
|
||||||
|
#define KC_MU KC_MS_UP
|
||||||
|
#define KC_MD KC_MS_DOWN
|
||||||
|
#define KC_MB1 KC_MS_BTN1
|
||||||
|
#define KC_MB2 KC_MS_BTN2
|
||||||
|
#define RAISE MO(_RAISE)
|
||||||
|
#define LOWER MO(_LOWER)
|
||||||
|
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
|
[_BASE] = LAYOUT(
|
||||||
|
KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P,
|
||||||
|
KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN,
|
||||||
|
KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_QUOT,
|
||||||
|
KC_LBRC, KC_RBRC, KC_MINS, KC_EQL,
|
||||||
|
KC_LCTL, KC_LSFT, KC_TAB, RSFT_T(KC_ESC),
|
||||||
|
KC_SPC, KC_LALT, KC_ENT, KC_BSPC,
|
||||||
|
LOWER, KC_LGUI, KC_RGUI, RAISE
|
||||||
|
),
|
||||||
|
[_RAISE] = LAYOUT(
|
||||||
|
QK_BOOT, KC_MPRV, KC_MSTP, KC_MPLY, KC_MNXT, KC_PGDN, MS_BTN1, MS_BTN2, KC_PGUP, KC_VOLU,
|
||||||
|
_______, MS_LEFT, MS_DOWN, MS_UP, MS_RGHT, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, KC_MUTE,
|
||||||
|
_______, MS_WHLL, MS_WHLD, MS_WHLU, MS_WHLR, KC_BSLS, KC_SLSH, KC_LBRC, KC_RBRC, KC_VOLD,
|
||||||
|
_______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______
|
||||||
|
),
|
||||||
|
[_LOWER] = LAYOUT(
|
||||||
|
KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN,
|
||||||
|
KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0,
|
||||||
|
KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10,
|
||||||
|
KC_F11, KC_F12, KC_GRV, _______,
|
||||||
|
_______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______
|
||||||
|
)
|
||||||
|
};
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
]]></description>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
|
||||||
|
<item>
|
||||||
|
<title> 'Serializing data in C'</title>
|
||||||
|
<guid>https://squi.bid/blog/Serializing-data-in-C/index.html</guid>
|
||||||
|
<link>https://squi.bid/blog/Serializing-data-in-C/index.html</link>
|
||||||
|
<pubDate>Sat, 09 Aug 2025 08:50:12 -0400</pubDate>
|
||||||
|
<description><![CDATA[This post seems to screw up my rss feed. You can read it on my website: https://squi.bid/blog/Serializing-data-in-C/index.html]]></description>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
|
||||||
<item>
|
<item>
|
||||||
<title>Why "suckless" software is important</title>
|
<title>Why "suckless" software is important</title>
|
||||||
<guid>https://squi.bid/blog/Why-"suckless"-software-is-important/index.html</guid>
|
<guid>https://squi.bid/blog/Why-"suckless"-software-is-important/index.html</guid>
|
||||||
|
121
index.php
121
index.php
@ -5,65 +5,112 @@
|
|||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<!-- prevent darkreader extension from messing with our already dark site -->
|
<!-- prevent darkreader from messing with our already dark site -->
|
||||||
<meta name="darkreader-lock"/>
|
<meta name="darkreader-lock"/>
|
||||||
</head>
|
</head>
|
||||||
<body style="background-color: #161617;">
|
<body>
|
||||||
<div id="master">
|
<div id="master">
|
||||||
<header>
|
<header>
|
||||||
<h1 id="font"><a href="/">Squibid's</a> Website</h1>
|
<h1 id="font"><a href="/">Squibid</a></h1>
|
||||||
</header>
|
</header>
|
||||||
<hr style="color: #f7f7f7;">
|
|
||||||
<div id="left">
|
|
||||||
<div id="group"> <!-- Welcome Section -->
|
<div id="group"> <!-- Welcome Section -->
|
||||||
<hgroup>
|
|
||||||
<h2 id="font">Welcome</h2>
|
|
||||||
</hgroup>
|
|
||||||
<p>
|
<p>
|
||||||
Hi my name is Squibid, and this is my website! I will be using it
|
Welcome to my website. I do a bunch of coding, I try to lean towards
|
||||||
for anything that I find interesting along with some of my personal
|
lower level languages (mostly C) as I find it more fun when there's a
|
||||||
projects and a blog.
|
challenge. As for the content of this website: I put blog posts up
|
||||||
<br><br>
|
when I've got something interesting to talk about and host my own git
|
||||||
Got a question? <a href="mailto:me@zacharyscheiman.com",
|
server with stuff I make (you can find the things I'm proud of below).
|
||||||
title="me@zacharyscheiman.com">Email me</a>.
|
</p>
|
||||||
It's not likely that I will respond fast as I do not check my
|
<p>
|
||||||
messages often.
|
Thank you for visiting, if you've got something you wanna say to me,
|
||||||
|
feel free to contact me somewhere below:
|
||||||
|
<ul>
|
||||||
|
<li><a href="mailto:me@zacharyscheiman.com">email</a></li>
|
||||||
|
<li><a href="https://github.com/squibid">github.com</a></li>
|
||||||
|
<li><a href="https://codeberg.org/squibid">codeberg.org</a></li>
|
||||||
|
</ul>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
|
||||||
<div id="group"> <!-- Git Section -->
|
<div id="group"> <!-- Git Section -->
|
||||||
<hgroup>
|
|
||||||
<h2 id="font", style="margin-bottom: 0;">Pinned Git Repos</h2>
|
<h2 id="font", style="margin-bottom: 0;">Pinned Git Repos</h2>
|
||||||
<p style="margin-top: 0;">
|
<p>My best projects:</p>
|
||||||
my best projects
|
|
||||||
</p>
|
|
||||||
</hgroup>
|
|
||||||
<p>My best repos are</p>
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://git.squi.bid/squibid/wiz">wiz</a> - An idle event
|
<li><a href="https://git.squi.bid/squibid/wiz">wiz</a> - An idle event
|
||||||
manager for Wayland. Written in C!</li>
|
manager for Wayland. Written in C!</li>
|
||||||
<li><a href="https://git.squi.bid/squibid/eat-it">eat it</a> -
|
<!-- <li><a href="https://git.squi.bid/squibid/eat-it">eat it</a> - -->
|
||||||
Eat It is a <a href="https://mpv.io", title="Mpv's Website">Mpv</a>
|
<!-- Eat It is a <a href="https://mpv.io", title="Mpv's Website">Mpv</a> -->
|
||||||
package manager written in <a href="https://lua.org",
|
<!-- package manager written in <a href="https://lua.org", -->
|
||||||
title="Lua's Website">Lua</a> with the intent of making Mpv
|
<!-- title="Lua's Website">Lua</a> with the intent of making Mpv -->
|
||||||
scripts easier to update and use.</li>
|
<!-- scripts easier to update and use.</li> -->
|
||||||
</ul>
|
</ul>
|
||||||
<p><a href="https://git.squi.bid/squibid">more...</a></p>
|
<p><a href="https://git.squi.bid/squibid">more...</a></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div id="right">
|
|
||||||
<div id="group"> <!-- Blog Section -->
|
<div id="group"> <!-- Blog Section -->
|
||||||
<hgroup>
|
<hgroup>
|
||||||
<h2 id="font", style="margin-bottom: 0;">My Blog</h2>
|
<h2 id="font", style="margin-bottom: 0;">My Blog</h2>
|
||||||
<p style="text-align: center; margin-top: 0;">
|
<a href="/blog/rss.xml", title="rss">(rss btw)</a>
|
||||||
<a href="/blog/rss.xml", title="rss">subscribe</a>
|
</hgroup>
|
||||||
|
<br>
|
||||||
|
<?php
|
||||||
|
$path = "blog";
|
||||||
|
$limit = isset($_GET['all_blog']) ? false : 5;
|
||||||
|
|
||||||
|
$files = scandir($path."/");
|
||||||
|
$entries = [];
|
||||||
|
$i = 0;
|
||||||
|
|
||||||
|
/* get all the files */
|
||||||
|
foreach ($files as $file) {
|
||||||
|
if (is_dir($path.'/'.$file) && $file[0] != ".") {
|
||||||
|
$tags = get_meta_tags($path.'/'.$file.'/index.html');
|
||||||
|
$entries[$i][0] = preg_replace("/\//", "", $tags["date"]);
|
||||||
|
$entries[$i][1] = $file;
|
||||||
|
$entries[$i][2] = $tags["date"];
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reverse the list */
|
||||||
|
rsort($entries);
|
||||||
|
|
||||||
|
/* print the blogs out */
|
||||||
|
printf('<table id="bloglist">');
|
||||||
|
$i = 0;
|
||||||
|
for (; $i < count($entries); $i++) {
|
||||||
|
if ($limit && $i > $limit - 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$file = $entries[$i][1];
|
||||||
|
$age = $entries[$i][2];
|
||||||
|
printf('<tr><td><a href=/%s/%s>%s</a></td><td class="date">%s</td></tr>',
|
||||||
|
$path, $file, str_replace("-", " ", $file),
|
||||||
|
$age ? $age : "¯\_(ツ)_/¯");
|
||||||
|
}
|
||||||
|
printf('<tr><td><a href=%s>%s</a></td></tr>',
|
||||||
|
isset($_GET['all_blog']) ? "/" : "/?all_blog",
|
||||||
|
isset($_GET['all_blog']) ? "...less" : "more...");
|
||||||
|
printf('</table>');
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
<div id="group"> <!-- People Section -->
|
||||||
|
<hgroup>
|
||||||
|
<h2 id="font", style="margin-bottom: 0;">Interesting People</h2>
|
||||||
|
<p style="margin-top: 0;">
|
||||||
|
(nvim users)
|
||||||
</p>
|
</p>
|
||||||
</hgroup>
|
</hgroup>
|
||||||
<p id="blogpreview">
|
<ul>
|
||||||
<?php include('misc/tools.php'); blog_entries("blog", 5); ?>
|
<li>
|
||||||
</p>
|
<a href="https://lunarflame.dev">lunarflame.dev</a>
|
||||||
<a href="/blog">more...</a>
|
- Fantastic game studio run by the amazing Adrian aka Phantom.
|
||||||
</div>
|
<li>
|
||||||
|
<a href="https://eggbert.xyz/">eggbert.xyz</a>
|
||||||
|
- Insanely intelligent developer who writes good blog posts and
|
||||||
|
great code.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
<!DOCTYPE HTML>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<title>Squibid's Site - 404</title>
|
|
||||||
<link rel="stylesheet" href="/style.css">
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
h1 {
|
|
||||||
color: var(--cyan);
|
|
||||||
font-family: sans-serif;
|
|
||||||
font-size: 404px;
|
|
||||||
width: 100vw;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<body style="background-color: #161617;">
|
|
||||||
<h1><a href="/">whoops</a></h1>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,27 +0,0 @@
|
|||||||
<?php
|
|
||||||
function blog_entries($path = "blog", $limit = false) {
|
|
||||||
$files = scandir($path."/");
|
|
||||||
$entries = [];
|
|
||||||
$i = 0;
|
|
||||||
|
|
||||||
foreach ($files as $file) {
|
|
||||||
if (is_dir($path.'/'.$file) && $file[0] != ".") {
|
|
||||||
$tags = get_meta_tags($path.'/'.$file.'/index.html');
|
|
||||||
$entries[$i][0] = preg_replace("/\//", "", $tags["date"]);
|
|
||||||
$entries[$i][1] = $file;
|
|
||||||
$entries[$i][2] = $tags["date"];
|
|
||||||
$i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rsort($entries);
|
|
||||||
for ($i = 0; $i < count($entries); $i++) {
|
|
||||||
if ($limit && $i > $limit - 1)
|
|
||||||
break;
|
|
||||||
$file = $entries[$i][1];
|
|
||||||
$age = $entries[$i][2];
|
|
||||||
printf('<a href=/%s/%s>%s</a><span>%s</span><br>',
|
|
||||||
$path, $file, str_replace("-", " ", $file),
|
|
||||||
$age ? $age : "¯\_(ツ)_/¯");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
73
style.css
73
style.css
@ -1,7 +1,5 @@
|
|||||||
/* root */
|
/* root */
|
||||||
:root {
|
:root {
|
||||||
--lr-width: 45%;
|
|
||||||
|
|
||||||
/* mellow theme colors */
|
/* mellow theme colors */
|
||||||
--bg: #161617;
|
--bg: #161617;
|
||||||
--fg: #c9c7cd;
|
--fg: #c9c7cd;
|
||||||
@ -29,70 +27,33 @@
|
|||||||
--gray05: #757581;
|
--gray05: #757581;
|
||||||
--gray06: #9998a8;
|
--gray06: #9998a8;
|
||||||
--gray07: #c1c0d4;
|
--gray07: #c1c0d4;
|
||||||
|
|
||||||
|
/* site background color */
|
||||||
|
--site-bg: var(--bg-dark);
|
||||||
}
|
}
|
||||||
|
|
||||||
html, body {
|
html, body {
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
}
|
background-color: var(--site-bg);
|
||||||
|
|
||||||
/* desktop mode */
|
|
||||||
@media only screen and (min-width: 100ch) {
|
|
||||||
#master {
|
|
||||||
width: 95ch;
|
|
||||||
}
|
|
||||||
div#master #left {
|
|
||||||
float: left;
|
|
||||||
text-align: left;
|
|
||||||
width: var(--lr-width);
|
|
||||||
}
|
|
||||||
div#master #right {
|
|
||||||
float: right;
|
|
||||||
text-align: right;
|
|
||||||
width: var(--lr-width);
|
|
||||||
}
|
|
||||||
p#blogpreview a {
|
|
||||||
max-width: 30ch;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* mobile mode */
|
|
||||||
@media only screen and (max-width: 100ch) {
|
|
||||||
#master {
|
|
||||||
width: 85%;
|
|
||||||
}
|
|
||||||
p#blogpreview a {
|
|
||||||
max-width: 50vw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
html, body {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
body[id=blog] {
|
|
||||||
background-color: var(--bg);
|
|
||||||
display: unset !important;
|
|
||||||
max-width: 80ch;
|
max-width: 80ch;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
div#master header {
|
#font, p, ul, ol, h1, h2, h3, h4, h5, table {
|
||||||
text-align: center;
|
|
||||||
font-size: 30px;
|
|
||||||
}
|
|
||||||
div#group hgroup {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
#font, p, ul, ol, h1, h2, h3, h4, h5 {
|
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
p#blogpreview a {
|
h1 {
|
||||||
float: left;
|
font-size: 3em;
|
||||||
white-space: nowrap;
|
}
|
||||||
overflow: hidden;
|
iframe[src="/blog"] {
|
||||||
text-overflow: ellipsis;
|
width: 100%;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
table#bloglist {
|
||||||
|
width: 100%;
|
||||||
|
td.date {
|
||||||
|
text-align: right;
|
||||||
}
|
}
|
||||||
p#blogpreview span {
|
|
||||||
float: right;
|
|
||||||
}
|
}
|
||||||
a {
|
a {
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
@ -100,5 +61,5 @@ a {
|
|||||||
color: var(--cyan);
|
color: var(--cyan);
|
||||||
}
|
}
|
||||||
a:hover, a:active {
|
a:hover, a:active {
|
||||||
font-style: italic;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user