It helps, that's for sure. But this sort of knowledge should not exist in the environment in any case. It should be part of the canonical package list, and not hidden away elsewhere. The whole idea of a dependency manager should be a centralized and consistent way to install everything you need and not be dependent on what values may or may not exist as a env-var.
Can you elaborate on the reasons why a package would need to declare that its dependencies must be installed from source rather than from pre-built binaries? I'm having trouble imagining a scenario where that capability would be used as anything other than a workaround for a deeper problem with how your dependencies are packaged.
Let's say you're developing a python package that relies on a native shared library. If you distribute it as a pre-compiled wheel, you're locking your users into the exact version and compilation flags, options, etc that you choose. So your question effectively boils down to "why do people need to compile their own software?".
Many reasons: you need more control, specialized hardware, testing newer versions of the library, maintaining an internal fork of a library, security, performance, the dev team maintains both the native library and python package and needs to keep them independent, or simply preference for dynamic linking against system libraries to avoid duplication.
> So your question effectively boils down to "why do people need to compile their own software?".
No, the question is why a package would need to decide for its users that the package and its dependencies must be installed the gentoo way. That's quite obviously different from why an end user would decide to install from source despite the availability of binary packages.
"There were a lot of interesting versions of BASIC done for Japanese machines this article misses (..)"
Most likely referring to MSX-Basic. Which shows it's (c) Microsoft on the startup screen.
Not the fastest, but a very full-featured Basic compared to most Basics around @ the time. Iirc it does non-integer math on BCD coded values. Single & double precision, so users can decide RAM use/speed/precision tradeoffs.
Maybe there were other Japanese machines using MS-supplied Basics before that. But if so, likely few (any?) after MSX was introduced ('83), since that was big in Japan leaving little room for 8-bit competitors.
My very first computer was a Spectravideo MSX computer which I got in exchange for writing some demo programs for the midwest distributor for the company. Fun little machine, although I still preferred Apple in general.
Very clever and great article! But it sounds pretty easy to write a cracker for it: Just rewrite the machine code to jump over the check. Or did I miss anything?
Edit: Guess it depends on the details and amount of "obfuscation" that he mentions.
>Very clever and great article! But it sounds pretty easy to write a cracker for it: Just rewrite the machine code to jump over the check. Or did I miss anything?
Nope, you did not miss anything. Many of these old DOS game floppy protections could be bypassed by a single byte change to the exe (or com, depending on the game) file. The time consuming part was working out exactly which byte to change.
Source: I cracked most of my DOS games back in the day, using nothing more than DOS's supplied 'debug' tool, so I did not have to go find, and insert, the floppy in order to play the game. On many of them, changing a single JC to JNC or a single JE to JZ (or the reverse) was all it took to bypass the copy protection. A few others took a few more bytes worth of patching, one had to convert a conditional into an unconditional branch or otherwise nop out a small code segment. The one that required the most effort was MicroProse's Apache helicopter simulator. They used the "weak sector trick" but the contents of the "weak sector" was also a small bit of the overall game code. So for that one I created a loader that hooked the disk interrupt and when it detected the weak sector read, it returned the sector data and the proper "disk read error" state for the rest of the game to work with.
> Just rewrite the machine code to jump over the check
Sure. It's even easier today: not only we have specialized software for cracking things, but we can even dump the memory contents and inspect them, patch up while the program is paused, and then rewind and try again from the same location. If we mess up, we can quite easily restart, just run the program again from our fast NVME drives(it will probably come straight from the OS cache). Heck, in some cases we can "fuzz" the program and let the computer try to figure out the winning combination! We can do this in parallel with our multiple cores.
Now think about the context back in the day. For the most part, people were trying to crack the copy protection using the same machine that ran the software. In the case of the BBC Micro, you could have anywhere from 16 to 128KB, depending on the model. In that era, it was often the case that you couldn't even run a debugger, because it wouldn't fit alongside the program you were debugging. And even if you could, their capabilities were nowhere close to what we have today and - depending on the hardware - some breakpoints you couldn't even reach (inside code that disabled interruptions - which was often the case for software that accesses disks).
It could be incredibly hard to find exactly what "jump" you had to change. If you messed up, this could mean a machine lockup. Now you have to reboot and load your stuff again from slow floppy media.
I did basically everything you mention, back in the day, although on a C64.
In many ways, things were much easier back then: Direct access to most of the hardware, flat memory layout, smaller and vastly simpler ISAs, smaller programs (meaning shorter disassemblies to wade through), no protected mode so you could overwrite anything in RAM and so on. And you wouldn't even have to do it live in-memory, just disassemble the program piecewise from disk. People did extraordinary things back then, and you vastly underestimate their capabilities. Sure, you had to write a lot of tooling yourself, but it was simpler times.
I am not trying to detract from the copy protection mechanism, which truly is ingenious. I was just genuinely curious whether I was misunderstanding anything from the article.
Or... what I also encountered and found to be the hardest to reverse engineer, having a block decode in the interrupt vector table using all registers including stack pointers as decode keys.
That meant that making a mistake would result in a tedious re-iteration.
Copying one of my old comments from slashdot... it sounds similar to Sierra's "cpc.com". While I was reading the article I wondered if the equivalent of this process for the 6502 (BRK/COP interrupt table?) would work.
Back in the 1980s Sierra On-Line used to copy protect their adventure games with a copy protection system which involved strangely formatted sectors on the original disk which were impossible to duplicate exactly using standard PC hardware.
The loader "sierra.com" used to call a copy-protection program "cpc.com" which loaded data from the disk to decrypt the main program and run it. cpc.com had some of the most obscure, twisty, awful code ever written to prevent debugging and it constantly used different methods to thwart stepping through the program using INT 3 (these were the days before Soft-Ice).
But the solution (or "crack") was just dead simple. Just fire up debug, step to the beginning of cpc.com, and copy the vector from INT 3 into the INT 13 vector - then cpc.com stops right at the point where the data from the disk is being loaded, so it can be copied.
Despite all the incredibly complex code, cpc.com had to read the data off the disk so there was no way the Sierra programmers could thwart this method.
My thoughts exactly. I spent a good amount of time learning about and cracking various schemes. It was never about distribution but about bragging rights and the different ways code was obfuscated. Most were disappointingly simple, others had more layers, very rarely found ones that needed special effort beyond say a person-day or two to solve.
The BFR runs on a mix of liquid oxygen and methane, according to Wikipedia.
Ignoring obvious scalability problems, wouldn’t it be possible to manufacture that with a pretty decent environmental footprint from various carbon neutral bio sources?
SpaceX plans to refuel the BFR on Mars with methane and oxygen produced via the Sabatier process and electrolysis [1]. They might do the same thing on Earth, even if only for the bragging rights of being carbon neutral.
def sumitup(n):
total = 0
for i in range(n):
total = total + i
return total
It was optimized quite well, but still had loops. I know this is a lot to ask, but I would have expected it to be possible to specialize it to a loopless variant:
def sumitup(n):
if n < 0:
return 0
else:
return n*(n-1) // 2
What is your impression of libjit? It looks really nice. I've only tried GNU Lightning, and I made Python bindings for it (although, today I would have used cffi to interface with it instead of my ctypes approach, because of the header files): https://github.com/cslarsen/lyn
I'd love to see a comparison of the various JIT libraries. I guess both give you optimizations and register allocation for free. Of course, the JITting speed is quite important as well.
It seemed pretty solid though I didn't do anything too complicated with it.
Mostly what messing around with it did was taught me that I had a lot to learn about compiler construction which is what I've been slowly doing since then.
Indeed I had already linked to your really cool project at the end. Perhaps I should have made it stand out more. The AST approach is more stable, as the Python bytecode can change between any release while the AST changes in a slower, evolutionary pace.
See https://docs.astral.sh/uv/reference/environment/#uv_no_binar...