u/peterfirefly

17 post karma · 5,980 comment karma · joined Oct 2012

peterfirefly

Was :(

He died in 2018.

peterfirefly

The need to avoid ambiguity is precisely why it's important to distinguish between f and f(x). They are not the same.

A lot of the trouble with teaching functions to kids is exactly due that common abuse of notation.

peterfirefly

Praksis siger noget andet.

Jørgen Dragsdahl vandt i Højesteret over koldkrigshistorikeren Bent Jensen på trods af at Bent Jensen havde beviser for sine påstande.

Et flertal af retten brugte et yderst søgt påskud om at ordet "agent" skulle betyde noget andet end det det i virkeligheden betyder (en der handler på vegne af andre -- i dette tilfælde en påvirkningsagent der handlede på vegne af Sovjetunionen og som havde jævnlige møder med sin KGB-føringsagent og fik penge for det) til at kende Bent Jensen skyldig.

Et mindretal på to højesteretsdommere gav selvfølgelig Bent Jensen ret.

Vi trænger virkelig til at vælge vores dommere bedre... :(

peterfirefly

Så laver man det sådan at brugerne af registret får kvoter. Nogle får store, nogle får små. Og en hel kommune skal ikke stå som en enkelt bruger, den må og skal have mange brugere med forskellige kvoter. Det skal også være bøvlet og besværligt at tildele store kvoter til brugere.

Der bør rulle hoveder for det her, fra minister og departementschef og ned til projektledere og programmører.

peterfirefly

De er selv skyld i at de også selv er inkompetente.

peterfirefly

Jeg har mødt iranere i Danmark der kaldte sig selv for mujahedinere og mente at problemet i Iran var mangel på rigtig Islam.

Det er selvfølgelig ikke nogen man gider snakke ret meget med.

Jeg har mødt andre som i den grad hader Islam (og religion i det hele taget).

peterfirefly

Grønland er enormt stort. Der er rigeligt plads til et åbent fængsel -- pivåbent og vindblæst -- oppe i Nordøstgrønland uden at forstyrre en eneste grønlænder.

peterfirefly

Blandt indvandrerne er det nok de mange der ødelægger det for de få.

(Men de ødelægger det også for alle os andre.)

peterfirefly

Haskell-168

peterfirefly

Består hendes iværksætteri i andet end at hun holder nogle foredrag om hvor god hun er til iværksætteri?

peterfirefly

Lone Frank hører ikke til på den liste.

peterfirefly

udtalte mig ukorrekt om somalieres intelligens,

Hvis man siger de i snit har en intelligens i nærheden af vores, så udtaler man sig vældigt ukorrekt (de ligger ca. to standardafvigelser under -- måske lidt mindre hvis de er født og opvokset her).

peterfirefly

meget kendt familie med indvandrerbaggrund

Det må være Melchior eller Foighel!

peterfirefly

har talt nedsættende om somaliere og griner af handicappede

Det er ikke i orden at grine af handicappede.

peterfirefly

Coffee.

peterfirefly

rightfully criticized for being a racist

wrongfully criticized for knowing facts and stating them publically.

he just was the first one who didn't back down after getting called a racist because he was a racist.

he is a brave man who didn't have much to lose... and he seems to be a tad autistic and therefore wants to tell things the way they are instead of the way most people prefer they are.

peterfirefly

My take on it is that all modern CPUs are eukaryotes (unless they are really tiny).

Back in the olden days, they were all prokaryotes (i. e. weird and different).

peterfirefly

Starting with a post in Italian and using strange descriptions in the title ("purely Topological" and "custom Microkernel OS") didn't do your case any favours.

peterfirefly

Ok, here's a quick comment dump...

At this stage, you'd probably benefit more from writing essentially the same gameboy emulator a couple of times but with different ways of structuring the code, different languages, different automated testing, different GUI integration, etc. There are lots of tests available for the Gameboy, both "test ROMs" and tests for individual components that you could play with.

I don't thing you would benefit at all from doing a Chip-8 emulator. That's for people who need a lot of hand holding just to get their first emulator done.

Just for fun, see what the C code compiles to (gcc/clang have an option to generate commented assembly code -- you can also use a disassembler or an interactive debugger). Just for fun, see what Python "machine code" your Python code compiles to -- there is a way to get a list of Python instructions for any Python function.

Also just for fun, see if you can find out how to profile your code. Don't go mad trying to optimize anything yet. Just measure it and be astonished at how inefficient everything really is. This will be your experience with your Python code -- but also with your C code for the first couple of versions. Don't do anything rash as a reaction to that inefficiency. Code that is too optimized becomes too unreadable -- and you will usually be optimizing the wrong things and the wrong way for the next couple of years, anyway.

Have a look at 'uv' for your Python code. Maybe use SDL for your C version instead of pygame.

Maybe use 'vcpkg' for SDL or maybe just download a new source release and unzip/untar it in a subdir or maybe use git modules.

Definitely take a look at the way your implemented the CPU in your Python code. That can be done so much cleaner and faster and shorter! That's probably also true of your first (and second, third, and fourth...) implementation of the CPU in C.

Finish the C version -- in a hacky, incomplete state if you must. Then maybe look at Rust or C++... but you should probably do some rewrites in Python and C first. Not because you have to, but because I believe that's the best learning path forward for you. You have managed to create a relatively large codebase that does something relatively difficult, which is very good. Most people can't do that. But -- and that's a big butt -- your Python code is quite clumsy. Your C code will also likely be clumsy. Learning how to write non-clumsy code is a transferable skill between languages. Not perfectly so, but still surprisingly so. If your Python code had been clean, I would have instead suggested to try a few more implementation languages as soon as possible, and to try implementing more sophisticated emulators as soon as possible.

There are many ways the parts inside an emulator can be connected. The most obvious ones end up with the CPU component being in charge and with most components knowing about most other components. That's not good. Ideally, no component knows about any of the other components. Ideally, the CPU is not in charge. Ideally, every component has some kind of (fast) unit test -- this is difficult if the code is structured badly. Ideally, there is almost no connection anywhere to outside world (pygame, in your case).

That's why I'm suggesting spending some time rewriting your emulator a couple of times, so you can learn the benefits of different ways of structuring the emulator. An interesting way, championed by "flohofwoe" is to model each component's interface on the physical pin interface of the original chips and to have the bus be in charge. This would be obvious for a typical 1980's home computer, built around a Z80/6502 chip, a timer chip, an interrupt controller chip, an I/O port chip, a video chip, a sound chip, etc. The Gameboy uses a couple of highly integrated chips with multiple components on each, so you would have to imagine a pin interface as if the components each had their own chip. Shouldn't be too difficult.

Also, I didn't find any disassembler in your Python code. Maybe I just wasn't looking hard enough? A disassembler is usually a very, very good idea... And they are super easy to write for something like a 6502 or a Z80 (a real one or the weird mutant in the Gameboy)!

At some point, start reading other emulators (mostly the good ones) to see how they solved the problems you have run into.

And remember: Writing is rewriting...

peterfirefly

If you choose Rust, there are a couple of things you'd likely want to install early on.

One of them is ripgrep. It is a faster and more modern grep. It knows that you will likely want to search in the source code of the repository you are inside, for example. You can still specify exactly which directories it should search in, if you really, really want to. You won't want to, though. It respects .gitignore. You'd likely want it whether you choose to use Rust or C++.

https://ripgrep.dev/docs/getting-started/

Notice how one of the ways you can install it is via "cargo install ripgrep"? You can install additional subcommands to cargo and just generally useful commands that are global (not cargo subcommands).

Another one is cargo-show-asm for, well, showing the generated assembler for a module or a library or a program. Very useful.

https://github.com/pacak/cargo-show-asm

The third one is "bat" which is like "cat" but with syntax coloring and more "betterness". You'd likely want it whether you choose to use Rust or C++.

https://crates.io/crates/bat

peterfirefly

You have probably always thought in terms of "what part of code owns this lump of data". If you do, you won't have problems with managing code in C or C++. Your Rust experience will be easy, the borrow checker will be obvious.

Lots of other people don't think that way. Their C or C++ code will have memory bugs. Their initial Rust experience will be hard and the borrow checker will be their enemy for a long time.

peterfirefly

Yes. Cargo is wonderful. No build script crap (there is an escape hatch if you really need to do something unusual), super easy handling of dependencies. That does have the unfortunate downside of many Rust projects having far too many unnecessary dependencies.

peterfirefly

I think I should add a note or two about vcpkg and SDL...

The preferred way of installing it is to clone the github repo and then run a shell script (there are different ones for different platforms). vcpkg usually works very well.

If you use SDL with Rust, then you may run into problems. Depending on the platform, it uses vcpkg to install SDL or it uses a git module to include the source code for a specific version of SDL. If the stars align badly (depending on platform etc) you may get an old version of the SDL source code that won't build with a newish version of CMake. The easiest fix may be to install an old version of CMake locally and make sure it's the one that gets run by the build script of the Rust wrapper for SDL (= set PATH correctly).

If you decide to use weird compilers on weird platforms, then vcpkg is still a good idea but your experience will be more "eventful" and "adventurous" than you'd like. By "weird", I mostly mean things like mingw that pretend to be Unix but on Windows.

If you want to use a Makefile or CMake or whatever with C++, instead of being tied to a GUI, there's a shell script you can run to get all the paths set correctly for whatever version of Visual Studio you are using. You can also choose to use the "developer prompt" in the Windows menu.

If you want to use SDL from WSL (the Windows way of letting you run Linux code), then there's an extra little problem. Microsoft has an automatic way of bridging Linux GUI apps to Windows (including OpenGL acceleration) but it is buggy.... and if you use SDL you will run into those bugs. They are not in Linux, X11, Rust, or SDL. They are in something called "wslg". X11 apps are handled by an X server (xwayland) that runs on top of Wayland. WSL2 uses a special Wayland server and Window manager that uses RDP to interact with Windows. The bugs manifest as incorrect drawing (wrong coordinate system or updates that don't happen), missing inputs, and crashes. The bugs can also happen without SDL but there's something about the way SDL works that makes them much more likely. You should be able to avoid them by using an X server that runs on Windows and connect your app to that (thus avoiding wslg) but I haven't tested it. The Microsoft Store has a couple + there are others on the web.

peterfirefly

To the op: Python has 'uv', which makes a lot of things much nicer, easier, and faster than before. 'uv' was inspired by Cargo -- and Cargo does it better!

peterfirefly

Say you want to learn Rust.

This is a good introduction and probably the best place to start:

https://doc.rust-lang.org/book/ch00-00-introduction.html

The only issue I have with that text is that modules are poorly explained. The way you declare them is not quite what you are likely to be used to from other programming languages. If you use this text, make sure you do all the homework. Don't skip anything.

One bad thing about both Rust and C++ is that many programmers go insane with abstraction masturbation and a desire to use the strangest and most esoteric features of both languages. This means that some libraries are a lot harder to get started on as a user than they needed to be. It also means that many (most, sadly) emulators written in those two languages are too hard to read and that some of them are unnecessarily slow.

Cargo is absolutely wonderful and something you will really miss with C++. vcpkg is a (complicated!) replacement for a small part of what Cargo does.

You will need some way to hook your emulator core up to video/audio/inputs. Maybe you prefer to use the native Windows API (if you are on Windows), maybe you prefer to use egui (lots of emulator writers have chosen that) or SDL (there are Rust bindings + tutorial + I think even youtube videos).

If you want to use the Windows API, then there's good news. Microsoft has made that really easy by providing a couple of Rust crates that support (almost) the entire Win32 API (it's also called Win32 for 64-bit platforms). They even managed to make them compile really fast, somehow.

If you want to use C++, then your best options are likely Win32 (if you are on Windows), Dear ImGui (egui was inspired by Dear ImGui), or SDL. You can chose to dump the SDL or Dear ImGui source code directly into your repo or use git modules or vcpkg. The latter might be the better option.

egui/Dear ImGui/SDL can all coexist with some Win32 use (or whatever your native API is). egui/Dear ImGUI and SDL can also coexist with each other to some extent. This means you don't have to feel locked in by your early choice of video/audio/input library. You can use SDL -- and still add Win32 dialogs, a native Win32 menubar, native input handling, etc. later, for example.

Rust is more tasteful than C++. It also implements many well-known good language features better than C++ -- and avoids the misfeature C++ is built around, namely objects with implementation inheritance.

If you have a good comp.sci. background, then you can think of Rust as just a modernized imperative-style ML with type classes and simple syntactic sugar for an extremely reduced form of objects (about as reduced as what Oberon had). With excellent tooling and an excellent ecosystem, of course. The debugging experience is not quite what it ought to be, but that's also true for C++.

Deallocations are handled implicitly using a variant of linear logic -- this is what all the reference/mutable/borrw/clone/copy stuff is about.

Things are only kept alive as long as they can be referred to (this also implies that ownership matters), immutable references can be shared (multiple readers is fine), mutable references can not (multiple writers is bad).

If you are used to thinking about which parts of your code owns which data, then you won't have any trouble. If not, you will. Lots of mediocre C and C++ programmers don't think in terms of data ownership, which is why they like refcounted and tracing garbage collected languages like Java, C#, and Python and why they really don't like the Rust borrow checker. Good ones will have close to zero problems with the Rust borrow checker.