ZH version is available. Content is displayed in original English for accuracy.
Advertisement
Advertisement
⚡ Community Insights
Discussion Sentiment
68% Positive
Analyzed from 1771 words in the discussion.
Trending Topics
#more#https#fable#code#stuff#function#data#github#nes#cool

Discussion (41 Comments)Read Original on HackerNews
Some low hanging fruit to reduce allocations: the discriminated unions in Instructions.fs could be [<Struct>], reusing field names to reuse internal fields.
Also, minor nitpick but I'm confused about some of the registers. They are already of type byte, the setters with `a &&& 0xFFuy` don't add anything over `member val A = 0uy with get, set`. I'm guessing this changed over time.
That's terrible on Fable's part, the least they could do is truncate. I wasn't aware Fable's translation is so naive.
There is some hope for humanity after all I suppose.
Even when I want code written in a different language (e.g., C/C++), I often still start by making a prototype in F#. This helps me nail down the logic without having to worry about things like allocation or layouts. Perhaps I could ask an AI to do this second step for me, and then use the F# implementation as an oracle. Anyway.
Even if you want to write all the code yourself (which is a fine decision), the only reason in 2026 to bang your head against a problem like this for 20 hours is if you really enjoy doing so.
(I'm surprised that "earlier AI models" didn't work for the author. For me, free-tier Gemini gets stuff like this correct all the time.)
Eventually I am sure someone at Microsoft noticed and rang the RLHF alarm, so GPT improved substantially. It seems pretty usable for F#. I am sure some unprincipled F#er is crushing it with agents these days. But I didn't think "oh boy they solved the plagiarism problem, let's go generate some slop!" I thought "oh great, now it's no longer going to be blatantly obvious when ChatGPT plagiarizes." I really don't want to roll a d100, or even a d1000, to completely compromise a core value of mine in in exchange for a productivity benefit. I'll just be slow and jobless, thanks. This is serious: I am getting into solar installations and junk hauling.
[1] The "students don't want to think" problem is much older than LLMs. In 2007 I took a senior-level PDEs class, and almost everyone copied my homework because I was actually motivated to study PDEs, and too psychologically weak to resist those mean lazy math majors. Then it happened again in math grad school! Actually unbelievable. Why are you even in the program?
For example, I usually like using the `Map` data structure, and that's a pretty neat immutable structure and is usually fine for most stuff, but when performance becomes critical, it's easy enough to break into a boring imperative loop with a regular hash map. If I keep everything contained into one function, I usually can avoid feeling super dirty about it.
There are basically two points to programming with immutable-first data. One, eliminate certain classes of data race concurrency bugs. Two, less mutable state in a given context makes it easier to reason about.
So, if you're inside a function scope and you aren't launching any concurrent operations from inside that function, you don't have to worry about benefit #1. If you're inside a function (and you're not reaching out for global mutable state), then the context you need to keep in your working memory is likely fairly small, so a few local mutable variables doesn't significantly harm "understandability" of the implementation (in most cases). So, you really don't have to worry about #2, either. Make your functions black boxes with solid "APIs" (type signatures), and let the inside do whatever it needs to make it work the best.
Just because premature optimization is the root of all evil, it doesn't mean we need to jump right to premature pessimization...
I will personally almost always prefer the pretty functional versions of things, and that's almost always what I start with. I like immutable data structures, and they are usually more than fast enough. Occasionally, though, you hit a bottleneck of some kind (usually in some form of loop), and you have to avoid all the beautiful functional stuff and go back to sad imperative stuff. When I do that, I usually try and keep it scoped to one function. Even within one function, I do find the persistent structures easier to reason about, but as you stated it's a small enough surface area to not be too irritating.
There are exceptions to this, of course. Sometimes for caching/memoizing I will make a global ConcurrentDictionary, and I'll use the interlocked thing to do global counters sometimes.
One thing I do want to try out is publishing it with native AOT. I had a lot of luck with that on one of my other F# projects, I got like a 75% speedup out of it. I understand the JIT is supposed to outperform native AOT in the long term but I haven't seen it reach that speed.
And sorry for the paranoia, I find a lot of people tried f# or even c# back in 4.x Framework era and think it hasn't changed.
https://gbatemp.net/threads/no-gmb-2-5-dos-full-version.6039...
I've got fond memories of using this to get a preview of Pokemon Gold before it was released in NA!
MetalNES, transistor level NES emulation https://github.com/iaddis/metalnes
While searching I also found a new one, VisualNES https://kaiokendev.github.io/nes/about
There is also one for GB https://github.com/aappleby/MetroBoy
MetalNES, transistor level NES emulation https://github.com/iaddis/metalnes
While searching I also found a new one, VisualNES https://kaiokendev.github.io/nes/about
There is also one for GB https://github.com/aappleby/MetroBoy
Speak for yourself
I mean, ideally, we'd run different color test patterns through, in different lighting conditions, to build a really detailed model, right?
I've been going through a lot of very old stuff recently and a lot of it is well preserved in a way but given enough years everything changes.
I don't think any original Gameboys have been made in twenty years or more.