Live data from Hacker News

The time the x86 emulator team found code so bad they fixed it during emulation

devblogs.microsoft.com

151–160 of 179 posts

Re: The time the x86 emulator team found code so bad they fixed it during emulation

#151

Earlier quoted context omitted.

> To be fair excel would erase places white that it wanted to write up to 9 times before it drew any black pixels I feel like I'm having a stroke trying to read this, what does it mean??

Well all they needed to do was erase the screen with white and draw on it, but their app's internal logic meant that they erased it more than once. I was capturing QuickDraw library calls - the low level graphics primitives, to figure out where the graphics time in apps was going and found out sometimes excel did it 9 times Of course users didn't see it more than once, but our hardware made all that wasted time run f…

It's more likely that one dev wrote the draw-cell code.

Another dev who's fixing a bug, realizes if they call a certain function either directly or indirectly, their particular bug gets fixed.

Oh, and as a side effect, the cell gets erased (again).

A few more fixes/new features added like this and the code is inadvertently erasing the same cell multiple times.

It takes a certain type of dev to step through in a debugger and Notice the app is doing way too much work and then to untangle the mess of code without causing regressions.

Re: The time the x86 emulator team found code so bad they fixed it during emulation

#152

Betting Alpha was the native architecture in question. It seemed to have the best support.

Yeah, but I thought DEC wrote the FX!32 translator for the Alpha. Perhaps Raymond was talking about those people and didn't want to mention that they weren't Microsoft people.

Re: The time the x86 emulator team found code so bad they fixed it during emulation

#153
post #150
post #140

Earlier quoted context omitted.

That's not how I remember these events when they were playing out. I distincly remember social media posts warning about the dangers of modifying game files, plus refusal to acknowledge the issue. Note there were 2 full weeks between the blog post and the update mentioning the bounty. I'm pretty sure the massive community outrage in between has played a role in it. But I don't have any sources and I was wrong about a…

Wowee two full weeks? You mean like a single sprint to discover, verify, and post PR about a perf patch that was good among the sea of rumors and reports a billion dollar game usually gets?

I mean like enough time to check the pulse with the community and walk back the initial confrontational response. I don't have a problem with when they fixed it. I don't have a problem with when they paid out. I wouldn't have a problem if they didn't pay out at all (why would they?). I have a problem with their initial reaction, which was full of the usual fearmongering against modders. (And a smaller problem with that it took an external contributor to finally make them implement a trivial fix for a massive usability issue that's been there for at least 6 years. It shows how much they don't care about their customers or the product they're selling unless the media get involved.)

Re: The time the x86 emulator team found code so bad they fixed it during emulation

#154
post #79

Earlier quoted context omitted.

Is it? I get what you're saying, but asking for 1 byte 65536 times, is indeed different than asking for 65536 bytes, 1 time. There may be reasons, such as when you pull off the end of a buffer, it shifts. And the buffer size is 1 byte. Or 10. Or whatever. No, I'm not saying that's why. I'm simply saying there is a difference between asking for 1 byte or 65k bytes of something. Even dd runs the same under Linux. dd bs…

> asking for 1 byte 65536 times, is indeed different than asking for 65536 bytes, 1 time. Yes it's different. As others have noted, the difference is what is returned if less than 65536 are available to read in the file: total failure vs partial read. There is, unsurprisingly, no requirement that it has an unnecessarily inefficient implementation to meet this behavioral requirement. (The C standard doesn't talk about…

Also you need to be careful what you read/write. In some cases.

As many examples out there use int/char etc to show how to use the thing. But if you switch to structs that fwrite can totally burn you if you use the sizeof call. As the sizeof a struct can vary between platforms and compilers. Depending on packing. Then endianness can sometimes mess you up. If you are reading/writing for yourself you can get away with a lot. But if you are trying to interop then you have to be wildly careful what you do.

fwrite is another one where people will do one byte at a time (same up to for the windows version). Bash out a loop, use the sizeof for the input to the for loop. copy and paste just doing 1 byte and you can easily end up here. One program I added a cache in front of the thing so it would always write on disk block boundaries and then come back for more. I started off with just packed struct sizes but the perf was just 'ok'. The file block boundary thing really made it fast. Not all OS's have a readahead/write buffer behind that call so perf can vary.

It is honestly such an easy mistake to make. As many of the examples/docs do not really show you why/how to use both of those calls in the way needed. You sort of have to stumble into it and work it out.

Once you see it you know. But until then you do not really notice if it is 'working'.

Re: The time the x86 emulator team found code so bad they fixed it during emulation

#155

> Anyway, my colleague found that there was one program that needed to allocate around 64KB of memory on the stack and initialize it. The standard way of doing this is to perform a stack probe to ensure that 64KB of memory is available, then subtracting 65536 from the stack pointer, and then initializing the memory in a small, tight loop. Actually, the standard way of allocating 64 kB of memory on the stack is to jus…

IIRC you have to probe every page of the stack on Windows. You cannot just subtract a value from ESP/RSP. If you don't probe every page in order, you get a page fault or some other exception (I don't remember which one).

The reason for this is to ensure stack overflows are detected. The OS places a guard page above the top of the stack, which will cause a segfault if accessed. That way stack overflows are guaranteed to crash rather than stomping on valid memory that belongs to something else. However, if a stack frame is larger than a page (say, because it includes a large buffer), then it is possible for the program to "jump over" the guard page and access memory beyond.

In order to protect against this, the compiler inserts some dummy reads or writes as needed to ensure every page is touched in order from bottom to top. This ensures the guard page is hit before the application has a chance to write to memory beyond it.

Here's an example: https://godbolt.org/z/oTbzTczM6

Re: The time the x86 emulator team found code so bad they fixed it during emulation

#156
post #15
post #14

To be fair it is possible that the developer enabled a special "unroll all loops, no matter what" optimisation flag during compilation. I agree it would be stupid for a compiler to even support such a flag, but those were the 1980s/90s.

Ahh... Good old funrollloops... https://www.shlomifish.org/humour/by-others/funroll-loops/Ge...

Heh, "funrollloops" reminds me of recompiling FreeBSD 4 on my thinkpad back in the early aughts. The word made me imagine some sort of processed breakfast cereal with too many additives.

Re: The time the x86 emulator team found code so bad they fixed it during emulation

#157

This reminds me of a story from 15 years ago, where I was developing a technology to download games on demand by hooking into the OS calls. There was a particular game that was superslow when this tech was applied. Original game loading took around 15-20 seconds, whereas once the tech was applied it took easily 3-5 min, even with all data already downloaded. When I started digging into it, I realized the reason was t…

Is this actually real? I thought fread just multiplied the two numbers together to compute a total size. Meanwhile, the Win32 API call ReadFile actually does do a separate system call if you call it multiple times.

Re: The time the x86 emulator team found code so bad they fixed it during emulation

#158
post #136

Earlier quoted context omitted.

Well my Hercules graphics card was only monochrome, but it was relatively high resolution.

I had a herc clone on the 286 machine I bought around 1987 and later added a Super VGA card. One cool thing about the IBM PC was that the monochrome and color graphic systems were sufficiently different in terms of memory map and ports so you could plug in two graphics cards and two monitors and that's what I had.

I think this was true for MDA (text only), but the Hercules had 64k of video memory at B0000, the latter half of which would overlap with the CGA card, and also VGA's text mode.

Re: The time the x86 emulator team found code so bad they fixed it during emulation

#159
post #26

This reminds me of a story from 15 years ago, where I was developing a technology to download games on demand by hooking into the OS calls. There was a particular game that was superslow when this tech was applied. Original game loading took around 15-20 seconds, whereas once the tech was applied it took easily 3-5 min, even with all data already downloaded. When I started digging into it, I realized the reason was t…

I used to be a graphics card/chip architect for macs in the early/mid 90s - our chips were the fastest, but some programs were resistant because they did stupid stuff: pagemaker invalidated the font cache every time it went thru its main loop, quark with ATM did an n*2 thing every time it wrote text etc etc. We had special hardware to accelerate text drawing and it did nothing because the software pissed it away. We…

In my 68K Mac emulator running on modern (or even decade-old) hardware, performance in the traditional sense is less of a concern, but other issues arise. The big ones include CPU-burning loops that wait for a length of time or for an interrupt-decremented counter to reach zero, as well as invalid memory accesses (which I've made crash — no NULL deref for you).

> We considered creating a plugin that fixed all these things, it would have been hard to maintain, in the end we travelled around to the people who made these apps and talked them through their problems

Since talking to developers is no longer an option, I actually do write "Such-and-such Tune-up" extensions that patch applications dynamically to make them run better (or at all) in Advanced Mac Substitute, or even Mac OS itself.

Re: The time the x86 emulator team found code so bad they fixed it during emulation

#160

Earlier quoted context omitted.

Is this why Windows takes so long to delete things?? Presumably those reads aren't done when using del from a console as that always seems a bit faster.

Its slowness is also a function of security software or any other file system "filters" (I believe they're called) are installed. For example, I run TortoiseGit which has a caching feature which is supposed to make it faster at showing what to commit. Disabling it increases the number of items I can delete per second in my Windows Explorer from about 1000 to about 3000 while making not making TortoiseGit operations m…

>slowness is also a function of security software or any other file system "filters"

nah, its equally slow on system with everything ripped out (defender, filters, even logging).

Post reply on HN