Friday, February 26, 2021

I exist!

Trans people exist. — OREO Cookie (@Oreo)

I was really doubting my own existence until I saw this tweet from Oreo. Thank you so much, Mondelez International! I'm still gonna buy the knock-off store brand cookies because they're cheaper, but good for you!

This has to be a social experiment. It looks like humanity failed it, though. A corporate social media manager literally made the most uncontroversial, non-political, objective statement of fact it's possible to make about trans people, and people lost their damn minds over it. This is dangerous. People are literally disagreeing with a cookie about my very existence.

These people can't be reasoned with. They don't live in our reality. They want nothing less than for us to just disappear. We can't let that happen.

Sunday, February 07, 2021

Gender euphoria

When discussing trans people and why they transition, there's a lot of discussion about gender dysphoria - and a lot of debate about what exactly defines it. When I first started questioning my gender, I was in complete denial about ever experiencing any kind of dysphoria. Yeah, I hated my facial hair, my voice, the way I looked in general, and I avoided mirrors and rarely took selfies, and never looked at them when I did. But that wasn't dysphoria, I just hated those things for no reason.

I never understood how some people could be so vain - staring at themselves in the mirror, taking tons of selfies, posting them everywhere...

Until I started seeing her.

The girl I was always meant to be.

Now I've got mirrors within arms reach in my home office, I created a shortcut on my laptop to show me a view from my webcam, and I take out my phone and snap a few selfies whenever I get the chance. There's nothing wrong with a little bit of vanity!

Seeing myself the way I was meant to be makes me very happy. It's the opposite of dysphoria - known in the trans community as gender euphoria. Many trans people, including myself, only realize they are experiencing dysphoria after experiencing euphoria for the first time. Dysphoria and euphoria are relative. If dysphoria is all you've ever felt, then it's difficult to recognize. This is why people say "You don't need dysphoria to be trans!" All that is necessary to be trans is to feel better as one gender other than the one you were assigned at birth.

I feel like everyone should explore their gender a bit. If you try out a different gender, and it doesn't work for you... well, now you know!

Monday, February 01, 2021

My new favorite microcontroller

I've been using various microcontrollers and single-board computers since 2013. I started with an Arduino Uno, and I fell in love with how simple it was to write real-time code that runs on bare metal on a tiny chip. Despite the limited RAM and storage space, it didn't seem restrictive at all! I've used a couple of Uno boards for various projects: a remote thermostat for my room A/C (at my dad's house), a "universal" TV remote, a modem rebooter, a furnace / AC control unit (at my current house), and... a clock. That I can update and set the time over bluetooth.

Of course, other manufacturers saw the success of the Arduino, and started making their own boards, either directly compatible with existing Arduino boards, or programmable through the Arduino IDE. In 2017, I got my Macchina M2, and started working on what would become my Volt mod project.

The problem

Last week, I was talking to my boyfriend about the Wifi-controlled outlets I had purchased years ago and reverse-engineered, and I lamented the fact that I could no longer get the exact same model and would have to do all that hacking all over again with a new model. Of course, if I could just build my own, it would be a lot easier. The problem is, Arduino boards with Wifi are expensive, right?

The solution

Let me introduce you to my new favorite microcontroller: The ESP8266. Built-in Wifi support, decently fast, plenty of RAM, a good amount of I/O pins, and dirt cheap. I got a pack of 3 for about $15. Wifi is super easy to use, especially if you're just doing UDP.

For this Wifi-controlled outlet project, I would also need some relays. I bought a pack of 4 dual-relay boards which are 3.3v I/O compatible. I already had an outlet box with a couple of outlets and a bunch of wire. Hooking it all up was very straightforward. The code for the ESP8266 is very simple and fits on a single page.

This is definitely going to be my go-to microcontroller for projects going forward. If you're interested, just search for "ESP8266" or "NodeMCU" on your favorite online retailer.

Wednesday, November 25, 2020

I am the queen of No Nut November!

After months of delays, they're finally gone! One more step to becoming who I truly am. No need to worry about testosterone anymore.

Thank you to the doctors, nurses, and hospital staff at the University of Kansas Bell Hospital who were very patient answering my questions and making me comfortable.

And a very special thank you to my sweetie dragon Scrydan, who was there with me the whole time. I couldn't ask for a better boyfriend!

Thursday, October 15, 2020

Saying goodbye to my two best friends

Not the ones in the Winnebago.

My two friends have forced testosterone on me for years. I've already blocked them, and I'm about to cut them out of my life entirely. Next month, I'm going in for surgery to get rid of these dysphoria dumplings once and for all.

Goodbye and good riddance.

Monday, September 21, 2020

Fixing an obscure Undertale bug

Undertale's 5th anniversary was a couple of weeks ago, so I decided to play through it again. However, when I tried to start it up, it just crashed right away. There was a lot of diagnostic output, but no error messages, just an exit. These kinds of bugs are difficult to diagnose, but I wasn't going to let that stop me from enjoying those goat hugs.

I ran Steam in a console window, and changed the launch options to run the game under a debugger:

That at least told me what the error was: SIGFPE - usually caused by an integer division by zero.

Reading symbols from /media/disk1/lstuff/steam/steamapps/common/Undertale/runner...(no debugging symbols found)...done.
(gdb) r
Starting program: /media/disk1/lstuff/steam/steamapps/common/Undertale/runner 
.
.
.
Thread 1 "runner" received signal SIGFPE, Arithmetic exception.
0x081d7332 in ?? ()
(gdb) 

What could it be trying to divide by zero? Maybe the rest of the output might give me a hint.

***************************************
*     YoYo Games Linux Runner V1.3    *
***************************************
CommandLine: -game game.unx
ExeName= /media/disk1/lstuff/steam/steamapps/common/Undertale/runner
MemoryManager allocated: 4031222
INI DisplayName=UNDERTALE
SavePrePend /home/ktpanda/.config/UNDERTALE/
GAMEPAD: Initialising Ubuntu support
Attempting to set gamepadcount to 4
display=0x9682cd0
Display Size(Pixels): 1920,1080
CreateDesktopWindow 640,480
Win #1
XF86VidModeExtension-Version 2.2
Got Doublebuffered Visual!
glX-Version 1.4
Icon: w=64 h=64
Creating window of width 640, height 480
sw=0 wh=0
WindowCentre: 640,300
Depth 24
Congrats, you have Direct Rendering!
sync = 1
**** GLX Extensions ***
GLX_EXT_visual_info GLX_EXT_visual_rating ...
Checking for GLX_EXT_swap_control
Vsync: GLX_EXT
DOUBLE BUFFERED
OpenGL: version string 4.6.0 NVIDIA 440.66.12
OpenGL: vendor string NVIDIA Corporation
OpenGL GLSL: version string 4.60 NVIDIA
Extensions:
GL_AMD_multi_draw_indirect GL_AMD_seamless_cubemap_per_texture ...
Anisotropic filtering supported, max aniso 16
This is where it would have set them fullscreen= 0, they are 0,0    displaywidth/h 0,0
Texture #1 16,16
Texture #2 16,16
Texture #1 16,16
Texture #2 16,16
finished(2)!!
Texture #1 1,1
Texture #2 1,1
finished(2)!!
Total memory used = 81515771(0x04dbd4fb) bytes

So one thing that stands out is the line that says displaywidth/h 0,0. If for some reason it was seeing the display resolution as 0x0, it is very plausible that trying to calculate something related to the aspect ratio would result in division by zero. But where is it getting that size from? Especially since earlier, it detects it correctly: Display Size(Pixels): 1920,1080.

Time to fire up xtrace. This utility intercepts all communication between the program and the X display server and dumps it. Undertale must be calling some weird function and misinterpreting the results.

***************************************
*     YoYo Games Linux Runner V1.3    *
***************************************
CommandLine: -game game.unx
ExeName= /media/disk1/lstuff/steam/steamapps/common/Undertale/runner
MemoryManager allocated: 4031222
INI DisplayName=UNDERTALE
SavePrePend /home/ktpanda/.config/UNDERTALE/
GAMEPAD: Initialising Ubuntu support
Attempting to set gamepadcount to 4
000:<: am lsb-first want 11:0 authorising with 'MIT-MAGIC-COOKIE-1' of length 16
000:>: Success, version is 11:0 vendor='The X.Org Foundation' release=11906000 resource-id=0x0a200000 resource-mask=0x001fffff [...] width[pixel]=1920 height[pixel]=1080 [...]
000:<:0001: 20: Request(98): QueryExtension name='BIG-REQUESTS'
000:>:0001:32: Reply to QueryExtension: present=true(0x01) major-opcode=133 first-event=0 first-error=0
000:<:0002:  4: BIG-REQUESTS-Request(133,0): Enable
000:>:0002:32: Reply to Enable: maximum-request-length=4194303
000:<:0003: 20: Request(55): CreateGC cid=0x0a200000 drawable=0x00000245 values={background=0x00ffffff}
000:<:0004: 24: Request(20): GetProperty delete=false(0x00) window=0x00000245 property=0x17("RESOURCE_MANAGER") type=0x1f("STRING") long-offset=0x00000000 long-length=0x05f5e100
000:>:0004:2168: Reply to GetProperty: type=0x1f("STRING") bytes-after=0x00000000 data='[...]'
000:<:0005: 20: Request(98): QueryExtension name='XKEYBOARD'
000:>:0005:32: Reply to QueryExtension: present=true(0x01) major-opcode=135 first-event=85 first-error=137
000:<:0006:  8: XKEYBOARD-Request(135,0): UseExtension major=1 minor=0
000:>:0006:32: Reply to UseExtension: major=1 minor=0
display=0x95bacd0
Display Size(Pixels): 1920,1080
CreateDesktopWindow 640,480
Win #1
.
.
.
000:<:003a: 16: Request(98): QueryExtension name='RANDR'
000:>:003a:32: Reply to QueryExtension: present=true(0x01) major-opcode=140 first-event=89 first-error=147
000:<:003b: 12: RANDR-Request(140,0): QueryVersion major-version=1 minor-version=5
000:<:003c:  8: RANDR-Request(140,8): GetScreenResources window=0x0a200003
000:>:003b:32: Reply to QueryVersion: major-version=1 minor-version=5
000:>:003c:3680: Reply to GetScreenResources: timestamp=0x42ae9f12 config-timestamp=0x0003cf23 [...]
000:<:003d: 12: RANDR-Request(140,20): GetCrtcInfo crtc=0x0000023a config-timestamp=0x0003cf23
000:>:003d:44: Reply to GetCrtcInfo: status=Success(0x00) timestamp=0x42ae9f12 x=0 y=0 width=0 height=0 mode=0x00000000 current rr=0 possible rr=Rotate_0,Rotate_90,Rotate_180,Rotate_270,Reflect_X,Reflect_Y outputs=; possible outputs=0x0000023e,0x0000023f,0x00000240;
sw=0 wh=0
WindowCentre: 640,300
Depth 24

Well, would you look at that!? GetCrtcInfo returns 0 for both width and height. This is an XRandR function, so its actual name is XRRGetCrtcInfo. This function is so obscure that searching for it brings up a few examples, some StackOverflow questions, and the header file where it's defined, but no actual documentation for it. I played around with the xrandr utility, hoping to figure out what's causing it to return zero, but nothing worked.

But it's still just a hypothesis that this one call is what's causing the crash. If I could just trick the game into thinking that it returned the correct size, then maybe it will work. The definition of XRRGetCrtcInfo looks like this:

typedef struct _XRRCrtcInfo {
    Time	    timestamp;
    int		    x, y;
    unsigned int    width, height;
    RRMode	    mode;
    Rotation	    rotation;
    int		    noutput;
    RROutput	    *outputs;
    Rotation	    rotations;
    int		    npossible;
    RROutput	    *possible;
} XRRCrtcInfo;

XRRCrtcInfo *
XRRGetCrtcInfo (Display *dpy, XRRScreenResources *resources, RRCrtc crtc);

I can use the debugger and break on the call to XRRGetCrtcInfo, then step out, then poke values into the structure it returns:

Reading symbols from /media/disk1/lstuff/steam/steamapps/common/Undertale/runner...(no debugging symbols found)...done.
(gdb)
(gdb) break XRRGetCrtcInfo
Breakpoint 1 at 0x804f4a0
(gdb) r
Starting program: /media/disk1/lstuff/steam/steamapps/common/Undertale/runner
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

***************************************
*     YoYo Games Linux Runner V1.3    *
***************************************
CommandLine: -game game.unx
ExeName= /media/disk1/lstuff/steam/steamapps/common/Undertale/runner
MemoryManager allocated: 4031222
INI DisplayName=UNDERTALE
SavePrePend /home/ktpanda/.config/UNDERTALE/
GAMEPAD: Initialising Ubuntu support
Attempting to set gamepadcount to 4
display=0x880ccd0
Display Size(Pixels): 1920,1080
CreateDesktopWindow 640,480
Win #1
XF86VidModeExtension-Version 2.2
Got Doublebuffered Visual!
glX-Version 1.4
Icon: w=64 h=64
Creating window of width 640, height 480

Breakpoint 1, 0xf7829d50 in XRRGetCrtcInfo () from /usr/lib/i386-linux-gnu/libXrandr.so.2
(gdb) finish
Run till exit from #0  0xf7829d50 in XRRGetCrtcInfo () from /usr/lib/i386-linux-gnu/libXrandr.so.2
0x082fc8f7 in ?? ()
(gdb) info registers
eax            0x888ccd0	143183056
ecx            0x0	0
edx            0x89606e8	144049896
ebx            0x873fae4	141818596
esp            0xffffa8a0	0xffffa8a0
ebp            0xf709db00	0xf709db00
esi            0x1002	4098
edi            0x895c170	144032112
eip            0x82fc8f7	0x82fc8f7
eflags         0x200282	[ SF IF ID ]
cs             0x23	35
ss             0x2b	43
ds             0x2b	43
es             0x2b	43
fs             0x0	0
gs             0x63	99
(gdb) p ((unsigned int*)0x888ccd0)[0]
$1 = 1133426070
(gdb) p ((unsigned int*)0x888ccd0)[1]
$2 = 0
(gdb) p ((unsigned int*)0x888ccd0)[2]
$3 = 0
(gdb) p ((unsigned int*)0x888ccd0)[3]
$4 = 0
(gdb) p (((unsigned int*)0x888ccd0)[3] = 1920)
$5 = 1920
(gdb) p (((unsigned int*)0x888ccd0)[4] = 1080)
$6 = 1080
(gdb) c
Continuing.
sw=1920 wh=1080
WindowCentre: 640,300
Depth 24

Success! It sees the proper display size now, and the game starts up!

But that's a lot of work I'd have to do every time I launch the game, especially given what happens near the end. Fortunately, Linux and some other Unix-like operating systems support a feature called LD_PRELOAD, which allows injecting a library into a program before it loads, allowing it to override functions in other libraries. I created a simple C library that I could use with LD_PRELOAD for an automated fix. I'm currently working on cleaning up the code to upload it.

Let me know if you see something similar! I couldn't find anyone else posting about this bug, so it must not be common.

Thursday, April 30, 2020

Ouch

I just did my first self-injection of estradiol valerate earlier! It went pretty well, even though I was extremely nervous and my hands were shaking. I recorded the process so I could review it - it took 22 seconds to actually stick the needle in. I'm sure it will get easier with time.

My doctor initially prescribed estriadiol cypionate, but it's not available as a generic, only under the brand name Depo-Estradiol. She changed it to estradiol valerate, which is generic and seems to be more common anyway. My insurance would cover the EV, but not completely. It was actually cheaper with GoodRX, with the caveat that it doesn't apply to my deductible. Yay, privatized healthcare.

On the subject of estradiol, I read an article about a clinical trial where doctors are going to try giving transdermal estradiol to cis men who test positive for COVID-19, because data shows that women are more likely to survive. I really hope this doesn't cause a shortage. There are already nutjobs making up stories about how this whole thing is a conspiracy to feminize men and turn them into "soy-boy cucks" or "simps" (or whatever their latest slur is for men who don't fall in line with what they think a man should be), with a good deal of racism thrown in for good measure. It's the kind of thing you laugh at until you realize they are 100% serious.