News for hackers. Stuff that matters.

apple1417

If you use OBS, a game capture works the same way, it hooks the DirectX (or whatever API) functions to grab the rendered scene directly. It often has issues picking up overlays because there isn't really any synchronisation, just whatever made the last detour fires first. Like the sibling commit says, you can stack detours, it's only an issue for OBS if something that runs after it renders more things to the screen.

There is a setting to make it pick up overlays, which works reasonably well, I'm not entirely sure how it's implemented.

The assembly gives a bit of a hint as to what's happening.

    main:
    
    unreachable():
            push    rbx
            ...
Due to the undefined behavior, it decides calling main must be impossible, so the easiest thing to do is just give up, don't bother defining the rest of it. You can also do the same with std::unreachable(). But the label for the function still sticks around for some reason, so when you jump to it, it falls through. Which leads to the really stupid fact that reordering the functions changes the behavior.

I assume there are good reasons they can't just completely delete the label. Maybe it would screw linking, or with cases where you deliberately have multiple labels for the same function. And if the effect is only visible due to undefined behavior, it's not technically wrong. But I have always thought this is such a stupid case, surely it can't be that complex to add a trap instruction, even in an optimized build you shouldn't really care if it slows down a function that's "never called".

Re:Performance Improvements in .NET 11 on Thursday September 17, 2026 @12:02AM (#49736248)
C# takes a lot of different roles. If all you're doing is higher level stuff, say you're only working on a local GUI app where you're waiting on the user 99% of the time, you probably don't need to understand it. But you can also treat C# as more of a low level systems language, maybe you need to optimise some number crunching in a server - and then, as with any systems language, being able to read it may help.
Re:Intrusive Linked Lists on Thursday September 03, 2026 @10:33AM (#49550439)
> If I do address math on the pointer in order to find a payload, then isn’t the payload tied into exactly one next pointer, and thus exactly one list?

The container_of macro takes the type and member - so for a different member it can subtract a different offset.

Going more basic, you could imagine creating something like:

    struct Node {
        Node* next;
        Node* next_10th;
        Node* next_100th;
    };
The normal, 10ths, and 100ths lists are distinct collections, this is the basic idea. The macros just help generalise it and make it more usable.
Re:uv: Deduplicate all files in the wheel cache on Monday August 31, 2026 @09:49AM (#49509791)
I have never gotten the speed argument either. Yes it's noticeably faster - but in all my projects it's 1s vs 0.1s, not enough to make a meaningful difference. Even in their benchmarks, the worst number they ever give for pip is 7s [1] (and those numbers are 2+ years old, with python's improvements pip should be doing a little better now). I just can't say I've ever cared about installing dependencies, something you do once, taking 7s longer. Nor do I care how long CI takes, it running in the background is the point.

The one use I can give it is for running scripts with inline dependencies. I have found it a noticeable improvement over pipx there. But that's more due to needing to parse dependencies every single launch, if it's something I use regularly I end up just installing them normally instead, and it's faster than either.

[1] https://github.com/astral-sh/uv/blob/main/BENCHMARKS.md

Re:RISC-V: They should have known better on Saturday August 15, 2026 @01:50PM (#49312652)
I worked on a project porting from an STM32L073 to a STM32U073, which management were assured was a complete drop in replacement. Well, it was only in the sense that you could drop one onto the old PCB. It became a running joke how many software compatibilities we ran into. My favourite was an "LCD clock disable" bit became "LCD clock enable". And this was for a specifically chip designed to be an easy replacement.
Re:GitHub has alternatives, but no replacement on Saturday August 01, 2026 @01:33PM (#49136507)
Last time I looked into self hosting Windows CI, it seemed like everything kind of expected you to install all your tools ahead of time, rather than anything containerised. I assume Nix helps with that? Are there any docs you can point me at?
>> the Tandem tslim X2 requires the user to "prime" the pump tubing with 10 units of insulin every time the pump shuts down or the cartridge is replaced.

> This happens with every pump in one way or another to avoid getting air instead of insulin

The tandem doesn't allow you to finish priming before it's used 10u. Even if you know it's fine, and can see drops of insulin coming out immediately, you've got to wait until it reaches 10u first. I took the author's complaint to be more about that.

I've only had my battery die a couple of times, and I use a fresh line every cartridge, so I've only found it mildy annoying. If you're American and often reusing them, I could see it being more grating.

Re:Ghidra by NSA on Monday February 16, 2026 @11:21AM (#47036915)
Yup. It was actually an openjdk crash, which was extra interesting.

I figured I probably could remove some passes, but being a lite user I don't really know/didn't want to spend the time learning how important each one is and how long they take. Ida's defaults were just better.

Re:Ghidra by NSA on Monday February 16, 2026 @11:11AM (#47036793)
Leading this by saying I've only used Ida free, I can't comment on Ida pro. I'm also a very lite user of both, I give name functions/vars, save bookmarks, and occasionally work out custom types, and that's about it, none of the real fancy stuff.

I was recently trying to analyse a 600mb exe (denuvo/similar). I wasted a week after ghidra crashed 30h+ in multiple times. A seperate project with a 300mb exe took about 5h, so there's some horrible scaling going on. So I tried out Ida for the first time, and it finished in less than an hour. Faced with having decomp vs not, I started learning how to use it.

So first difference, given the above, Ida is far far better at interrupting tasks/crash recovery. Every time ghidra crashed I was left with nothing, when Ida crashes you get a prompt to recover from autosave. Even if you don't crash, in general it feels like Ida will let you interrupt a task and still get partial results which you might even be able to pick back up from later, while ghidra just leaves you with nothing.

In terms of pure decomp quality, I don't really think either wins, decomp is always awkward, it's awkward in different ways for each. I prefer ghidra's, but that might just be because I've used it much longer. Ida does do better at suggesting function/variable names - if a variable is passed to a bunch of functions taking a GameManager*, it might automatically call it game_manager.

When defining types, I far prefer ida's approach of just letting me write C/C++. Ghidra's struct editor is awkward, and I've never worked out a good way of dealing with inheritance. For defining functions/args on the other hand, while Ida gives you a raw text box it just doesn't let you change some things? There I prefer the way ghidra does it, I especially like it showing what registers each arg is assigned to.

Another big difference I've noticed between the two is ghidra seems to operate on more of a push model, while Ida is more of a pull model - i.e. when you make a change, ghidra tends to hang for a second propagating it to everything referencing it, while Ida tries pulling the latest version when you look at the reference? I have no idea if this is how they actually work internally, it's just what it feels like. Ida's pull model is a lot more responsive on a large exe, however multiple times I've had some decomp not update after editing one of the functions it called.

Overall, I find Ida's probably slightly better. I'm not about to pay for Ida pro though, and I'm really uneasy about how it uploads all my executables to do decomp. While at the same time, ghidra is proper FOSS, and gives comparable results (for small executables). So I'll probably stick with ghidra where I can.

Re:Threat Actors Expand Abuse of Microsoft Visual Studio Code on Thursday January 22, 2026 @06:26AM (#46717823)
When I used it, the one use case I used it was to automatically launch a Jekyll server - if I'm working on a site I'm almost certainly going to want to look at my changes in the browser. Now that I've switched I just run one extra command, it wasn't a big saving, but it was kind of nice.
Re:You Can't Fool the Optimizer on Wednesday December 03, 2025 @08:09AM (#46134071)
The MSVC linker has a feature where it will merge byte-for-byte identical functions. It's most noticeable for default constructors, you might get hundreds of functions which all boil down to "zero the first 32 bytes of this type".

A quick google suggests it's called "identical comdat folding" https://devblogs.microsoft.com/oldnewthing/20161024-00/?p=94...

My most common source of unintentional BOMs is powershell. By default, 'echo 1 > test' writes the raw bytes 'FF FE 31 00 0D 00 0A 00'. Not too likely for that to end up in a shell script though.
Re:Problems with C++ exceptions on Wednesday November 12, 2025 @06:55AM (#45899055)
In normal use it's essentially the same yes. The one interesting edge case that might catch some people out is there's actually nothing special about std::exception, you can throw anything, "throw 123;" is valid and would skip any std::exception handlers - but you can also just catch anything with a "catch (...)".
Re:The lazy Git UI you didn't know you need on Tuesday November 11, 2025 @02:07AM (#45884827)
I recently started working on a repo which historically had 100+ parallel branches. I've been jumping between a few tools recently trying to find something which handles browsing these sanely - I always liked browsing graphs, but the sheer amount of branches ruins most of them.

Currently the best workflow I've worked out is just a plain

    git log --oneline --graph -- <dir>
Followed by showing the specific commits. But this doesn't work so well with MRs that touched many files across different dirs. Anyone have suggestions for tools that might handle this better?
Re:Linux gamers on Steam cross over the 3% mark on Monday November 03, 2025 @06:17AM (#45797913)
An interesting example was Borderlands 2. The game originally had a native port by Aspyr, which worked quite well. 5 years pass and they release a new update and DLC - but they neglected to update the ports. 5 more years pass, then at some point in the past year or two they just plain removed the native Linux packages. They didn't announce it or anything so not 100% sure when. So these days when you install it you always get the (updated) Windows build under proton.

I'm a little sad we lost the native version, but on the other hand running it under proton just works, as I'd been doing for years, and the game would never have been updated otherwise.

Re:Linux gamers on Steam cross over the 3% mark on Monday November 03, 2025 @06:01AM (#45797833)
If you have an older game which still uses dx9, dxvk can give a decent little performance boost - even if you're running on Windows. It's kind of magical that adding a translation layer is able to improve performance.

In more modern games using dx11/12, I've always noticed a small loss like you'd expect. I haven't properly benchmarked any but I suspect a game with native Vulkan support would do pretty similarly, and might come out on top due to CPU load.

They exist, but one of the problems is they're not particularly good cubes. While it might help you learn the basics, not being able to handle it like a speedcube means they're probably not going to help you get faster.

https://m.youtube.com/watch?v=l-TWH5W-1fw

https://exmarscube.com/product/ex-mars-ai-robot-cube/

That being said, while looking up those links, I found out that, since I got out of the hobby, smart cubes have become a thing, and are made by real speedcube manufacturers.

https://www.gancube.com/products/gan-356-i-carry-smart-magic...

This is an easier problem to solve. I'm not sure if you have to solve it first or if it can identify pieces on power up, but after that it's just tracking rotations, which can be done from the (fixed position) centres alone. But if an actual speedcube manufacturer can already fit those electronics in without comprising performance, I can't imagine it's that much harder to fit some addressable LEDs on some slip-ring-esque connections. Must just not be much of a market.

Re:Fil-C: A memory-safe C implementation on Wednesday October 29, 2025 @02:19AM (#45743269)
I'll preface this by saying my experience is with embedded, not kernel, but I can't imagine MMIO is significantly different.

There would still be ways to make it work with a more restricted intrinsic, if you didn't want to open up the ability for full pointer forging. At a high level, you're basically just saying "This struct exists at this constant physical address, and doesn't need initialisation". I could imagine a "#define UART zmmio_ptr(UART_Type, 0x1234)" - which perhaps requires a compile time constant address. Alternatively, it's not uncommon for embedded compilers to have a way to force a variable to a physical address, maybe you'd write something like "UART_Type UART __at(0x1234);". I believe this is technically already possible using sections, it's just a massive pain creating one section per struct for dozens and dozens.

Unfortunately the way existing code does it is pretty much always "#define UART ((UART_Type*)0x1234)". I feel like trying to identify this pattern is probably too risky a heuristic, so source code edits seem required to me.

On a recent 12h Air New Zealand flight I went on they offered free wifi for everyone. They say you can:

- Browse the web.

- Send and receive emails and messages.

- Check and post to social media

In practice I think they just whitelist a few messenger apps. Everything else was unusable - I couldn't even load this site. Only had my phone so couldn't check if I was actually receiving any bytes from other sites, but it at least wasn't immediately blocked.

Re:An Opinionated Critique of Duolingo on Wednesday October 01, 2025 @01:19AM (#45434490)
2800 day streak here, primarily in Finnish. I haven't been a fan of the app for a long time, but the problem I've always had switching is the question: What else? There might be a thousand different Spanish courses, but for less popular languages there just aren't many choices, the fact that they still host one is great. Yes I haven't really learnt much, it's more maintaining what I do know, but I'd've lost it without.

Incidentally I do think Finnish is one of the cases where it could work well. The way I see it the difficulty in learning Finnish is primarily learning an entirely new vocabulary, the grammar and sentence structure isn't that hard, and Duolingo could work well to teach you thousands of new words. The problem is they have a very limited amount of exercises, to the point my phone's auto complete can solve half of them.

---

Please don't just link me stuff you've found on Google, I've tried them all. My favourite was Yle Kielikoulu, but that's been shut down.

Re:We All Dodged a Bullet on Tuesday September 09, 2025 @07:15PM (#45190793)
I once got a "log into phishing training" email which spoofed the company address. No one even saw the email, it instantly hit the spam filter.

Our infra guy then had to argue with them for quite a while to just email from their own domain, and that no, we're weren't going to add their cert to our DNS, and let a third party spoof us (or however that works, idk). Absolutely shocking lack of self awareness.

Re:I Run a Full Linux Desktop in Docker Just Because I Can on Saturday August 23, 2025 @05:09AM (#44994543)
Not OP, outside of games I keep a dual boot pretty much exclusively for Visual Studio - imo it's one of the best debuggers I've ever used. I know gdb is just as powerful if not more, but it is so much less ergonomic, even with the different frontends I've tried. Edit and continue for C/C++ is such a killer feature too. I stick away from msbuild or using it as an editors it's purely my debugher.

Granted it helps that a lot of the time I need "advanced" debugging relates to msvc/windows specific issues, which while I could run it in wine, it's just easier if I'm on windows anyway.

Re:How to Run an Arduino for Years on a Battery on Sunday July 20, 2025 @05:50AM (#44623456)
On one of the projects I worked on, I brought a PIC16 down to ~20nA - where our fancy meter only went down to 10nA precision. It was completely unnecessary, but I'm still quite proud of it.

For more standard cases, the 43uA from the article is roughly the same order of magnitude you'll get from pretty much any micro in sleep mode, after doing your first pass low power optimisation. The stuff I normally work with gets about 10. The thing is just, most of the time, that's low enough already - for this project 2500mAh/43uA = 6 years of sleeping. The bigger factor is the current it consumes while awake - and that's where the Arduino's a bit of a letdown, the stuff I normally use is only in the order of 100uA while awake.

Re:Hacking Coroutines into C on Sunday July 13, 2025 @04:09PM (#44553255)
I've worked on several low power projects, while yes we needed an interrupt to wake the processor, they all still used polling for all the actual button handling. At worst the interrupt just set a flag. It's actually kind of amazing how polling turns the main loop into a denounce filter, entirely for free.
Having run into similar problems several times, I've also never really been satisfied with the solutions. You have to have different types to cause compile errors, but then you have throw those types away whenever you perform any actual operations on them.

    struct TypeA { int inner; };
    struct TypeB { int inner; };

    struct TypeA a1, a2;
    // whoops
    TypeB result = {.inner = a1.inner + a2.inner};
Don't get me wrong, where I've used this sort of pattern it's definitely caught issues, and it definitely massively lowers the surface area for this type of bug. But I still feel like it's quite fragile.

The use case I felt worked best was seperating out UTC datetime vs localised datetime structs - mainly since it's something you already had to use function calls to add/subtract from, you couldn't play with raw values.

Re:Detecting if an expression is constant in C on Tuesday April 22, 2025 @03:15PM (#43765322)
I've seen something related, which returned a bool instead of failing compilation, be used to switch between a path the optimiser could inline and some assembly. You could probably use this to make sure it was always inlined.
Re:Botswana Successfully Launches First Satellite, Botsat-1 on Thursday March 27, 2025 @06:23AM (#43492041)
It depends on what orbit you want. Due to the latitude you'll end up pretty inclined by default - which is bad for equatorial orbits sure, but a good start for polar ones. At a public session I went to several years back they spoke of specifically trying to attract polar launches for that reason.
That was actually recently added as a built-in feature

https://code.visualstudio.com/updates/v1_97#_git-blame-infor...

Like the sibling comment, I didn't want to run all of GitLens just for it, but now that it's a built-in I've also been finding it quite useful.

Re:The features of Python's help() function on Friday March 07, 2025 @11:50PM (#43297583)
Reading the PEP for adding it, it seems primarily concerned with mirroring how the C builtins generally don't allow it, for performance.

https://peps.python.org/pep-0570/#rationale

That being said, you can find quite a lot of uses in the modules written in Python - though I'm not going to pretend I can tell you the reasoning for all them.

  grep "/\s*[,)]" /usr/lib/python3.13/ --recursive --include "*.py" --exclude-dir site-packages
In my own code, the main use I've found is that they don't "reserve" a slot in kwargs - this is totally valid code:

  def func(x, /, **kwargs):
    print(x, kwargs)
  func(1, x=2)
You could've worked around it by taking a dict before, but it's just a lot friendlier being able to take args as normal.

Older »