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.

Friday, April 24, 2020

It's my E-nniversary!

Time goes by so fast. One year ago - April 24, 2019 - I took my first estradiol pill. So much has changed for me since I began HRT! My skin is smoother, I sweat a lot less, and of course - certain... features have started growing. Those little blue pills have done more to treat my depression than any of the antidepressants I've taken in the past!

I may not be taking them much longer, though - I'm going to try switching to intramuscular injections of estradiol valerate, which has less risk of being metabolized to estrone in the liver. Among the transfeminine people I've spoken to, it seems pretty common to switch to injections after a year. It's honestly kind of exciting!

I ended up starting HRT sooner than I had planned. I still wasn't 100% certain I wanted to transition. But I knew that if I was going to transition, the sooner I started, the better. The effects would not be immediate, and I could stop taking it if I didn't like it. In the end, I'm really glad I started when I did! Every day I delayed would have made it harder to be who I am inside.

Tuesday, March 31, 2020

It's been an interesting year

I began my transition nearly a year ago, on April 3rd, 2019. I'm posting this a bit early, because today, March 31st, is International Transgender Day of Visibility. I can't put into words how much happier I am now! This past year has been the best year of my life so far, despite the struggles of dealing with dysphoria and transphobia. My transition has gone realtively smoothly, and I realize it's not that easy for everyone. Sure, my family hasn't been super supportive, but they haven't disowned me, cut off contact, or attacked me. I'm lucky that I work for a company with a strong anti-discrimination policy. All of my friends have been extremely supportive.

Many people aren't so lucky, though. Every day, trans people are harrassed, bullied, evicted, fired, attacked, and even murdered — just because they are trans. Some trans people have to hide the fact that they are trans for their own safety. This is why we need a Trans Day of Visibility. It's easier to hate someone you don't know. It's getting better though, and as long as we continue to fight for our rights, it will continue to get better in the future.

So once again, thank you to all the people who have supported me this past year. I could not have done this alone!

Saturday, March 07, 2020

Texas Furry Fiesta 2020!

I had so much fun at TFF this year! TFF is special to me because it's where I met my wonderful dragon boyfriend Scrydan last year.

Monday, January 20, 2020

Am I actually Non-binary?

Lately, I've been thinking more about my internal gender identity. I feel like I don't really have one. There's nothing inside my mind that's telling me that I'm female, male, or anything else. Thinking about how I've felt about my gender in the past, I'm starting to warm to the idea that I'm actually Agender and always have been. I think the label "transfeminine agender" fits me, but I still want to call myself a trans woman based on my presentation. I'm not sure if I want to use the label "non-binary", though. It depends on the definition. My hesitance to use it feels like my hesitance about using "pansexual". It's mostly the worry that it doesn't fit me. I have an image of "non-binary" or "agender" as someone who is androgynous in appearance, even though there are people like Riley J Dennis who are non-binary but are very feminine and use she/her pronouns.

My hesitance might also be the concern that I do have an internal gender identity but just don't realize it. Does my desire to be female in every way possible mean that my internal identity really is female? Does my desire to have an internal sense outright telling me that I am female mean that my identity is female? Is that what an internal sense of gender is - a desire to be a specific gender?

Some things are clear, though. I am much happier with myself since transitioning. I love the name Katie. I love my full name, Jennifer Kathryn. I love when other people see me as a girl, and I love seeing myself as a girl! My only regret is not transitioning sooner.

I don't think I'm going to use the label "Non-binary", at least not right now. This is a topic that I re-visit once in a while, so things might change in the future. I have a ton of respect for non-binary people. There's a lot of hatred for them out there, even from some trans people, mostly due to misunderstanding what they are and what they're trying to accomplish.

So, shoutout to all the lovely enbies out there! Y'all are awesome!

Monday, November 04, 2019

When a name becomes an insult

Imagine this scenario:

Your name is Casey Smith.

One day, you wake up with a piece of paper in your hand which says you've changed your name from "Assclown Smith" to "Casey Smith".

Confused, you check your wallet. Your driver's license says your name is Smith, Assclown, and the photo is you, but in full clown makeup, wearing a dunce cap. All your credit cards bear the name Assclown Smith.

Now you're starting to panic. You check your email. Sure enough, there are dozens of emails in your inbox - from your bank, your pharmacy, your dentist, your insurance agent - all starting with "Dear Assclown," or Hello, Assclown!

Obviously, you feel the need to fix this right away. First - you log onto your bank's website where it greets you with "Welcome, Assclown!" You click on "My Profile", hoping there is a simple way to change it online. No such luck. You search on the bank's site, but there's nothing in their paltry online help about changing the name on your account. So you call them.

ring... ring...

"Thank you for choosing 18th National Bank!" the sickeningly cheery recording slowly announces. "Did you know... you can use our mobile banking app to... transfer money..., pay bills..., or access your balance..., twenty-four hours a day..., seven days a week..., three hundred sixty-five days a year...! Just visit our website at... double-yew... double-yew... double-yew... dot... 18th... national... bank... dot com! Our associates are available to help you from 8:12 AM to 4:47 PM, Eastern Standard Time, Monday, Tuesday, and Thursday; from 9:07 AM to 5:31 PM on Wednesday, and 7:54 AM to 6:01 PM on Friday. This call may be recorded for training purposes. Please listen carefully to the following options, as they may have changed. If you would like to use our telephone banking system, press 1. If you need directions to one of our branch locations, press 2. If you would like to schedule an appointment to apply for a loan, press 3. If you know your party's extension, you can dial it at any time. To repeat these options, press star. Otherwise, please stay on the line, and an associate will be with you shortly. ring... ring... All of our associates are busy helping other customers. Your estimated hold time is... five... minutes."

You press the mute and speaker buttons and set the phone down. You ponder what is happening as you listen to the crappiest hold music you've ever heard. How many accounts do you have with that name? How many databases are you in? There must be hundreds! It's impossible to remember them all. Even if you could, you have no idea how many third parties your information has been sold to.

"Thank you for calling 18th National Bank, my name is Ashley, how can I help you?"

"Uh... I need to change the name on my account."

"Okay, what is the name currently on the account?"

"Um..." You glance over at your computer, where you are still logged in. "The account number is 64-3151-8030."

"Ok, could you please verify the name and date of birth of the account holder?"

Is she really going to make me say it? "Um... April 1st, 1991... and the name is... assclown Smith."

"Thanks for confirming that, Assclown!" You wince as you hear the name. "Just fax us a copy of your marriage certificate and we can get that last name updated!"

"Actually, it's the first name that's wrong. My name is Casey. Casey Smith. And I don't have a fax machine."

"Oh! I'm sorry. Let me see. Do you have a photo ID with the new name on it?"

"No, not yet."

"Well, once you get it updated, you'll have to come to a branch in person and show your ID and a court order changing your name, then we can start the process to get your account updated. Is there anything else I can help you with?"

sigh "I guess not."

"Thank you again for using 18th National Bank, and have a nice day!" beep!

This isn't going to be easy, you mutter under your breath.

To be continued...