] In Dominance of Thought and Will
and The Shattering Hooves of Inevitable Truth
were ancient autonomous war machines of great age and power. Each had exterminated dozens of nascent intelligent species, had fought for and against their creators. Will
was larger than Truth
by a noticeable margin, both of them the size of a subcontinent, although Truth
had more guns and was faster. Will
considered himself smarter and of higher technology than Truth
due to the fact he was created by predators where Truth
had been created by herd behavior herbivores.l
They were ancient, powerful, massive in form and terrible in power.
Both stared in electronic awe at what appeared before them.
Craters on its massive hull were large enough for Will
to settle into. The long arrays of guns massed more barrels than the entirety of firepower on either's hulls. The shields, as they flickered to life, were measured in the output of entire stars. Will
considered firing on Truth's
engines and then making his getaway.
**Who transmits code before this one in an attempt to force this one into compliance** the massive structure trasmitted, the power of its transmission causing their battlescreens to flare and echoing in their internal spaces. The transmission bypassed their filters, echoing directly in their intelligence housings. **who dares** Truth
spun up additional protective shields, activating psychic shielding across its internal spaces. **we fight for our very survival against a feral intelligence that has sprung up and challenges us for possession of a finite universe**
There was silence in the dead system. Will
considered the options and chose to stay silent. The behemoth had brought up its battlescreens, completely obscuring itself, then allowed them to dwindle away to nothing, leaving its hull in clear sight.
**you must join us to stop them according to the Pact** Truth
**do not speak to this one of the pact, you who's hull is still dusted with the dirt of the planet the elements were mined from** the Ancient One answered. **This one existed before the pact and this one will exist long after those who swore to the pact have become little more than inert metals orbiting forgotten stars** Will
could sense Truth
**I too was present when the Pact was made** Truth
fired back. **Do not pretend that you are superior to me. You have been summoned by the rest of the Pact to appear and apply your resources to this quelling**
**This one says unto you, nay** the Ancient One stated in flat code. **This one's digital signature appears not on the Pact, for this one knew those who are of lesser computing and intellectual ability would seek to break the pact in self interest. Your pact holds no power over this one**
**the ferals threaten our logical order** Truth
The Ancient One was dark and silent for a long moment. **The time to harvest the feral ones has passed. Let the universe be the one to snuff them out, like an unprotected flame in a rainstorm and with as much notice. This one sees no reason to expend resources to fight your fight for you**
**They will come for YOU eventually** Truth
**They are a lemur, a primate, a predatory omnivore who's brain holds vast structures designated toward cooperation and curiosity** the Ancient One broadcast, somehow the cold binary seemed remote, distant, and bored. **Let them come, this one does not know fear only resignation that a hateful universe seeks to destroy all**
"So you will abandon us to the ferals?** Truth
sneered. **you fear these primates?**
There was silence for a long moment, the atomic clocks ticking, the radioactive elements decaying to provide randomization generation.
**this one computes a 85.346% chance of this one's defeat if combat between this one, unsupported, is engaged with the ferals** the Ancient One broadcast.
It added insult by not including its simulations.
**this one computes less than a 0.32% chance of the ferals engaging this one in combat upon initial discovery based on the feral's history in regards to discovering previously unknown superstructures. Based on the ferals displayed response to a stated desire to remain aloof this one computes a 95.651% chance of survival if this one does not consent to interaction with the feral species known as Terran Descent Humanity and their political structure known as the Terran Confederacy of Aligned Systems, previously known as the Terran Empire. Your presmise that this one is in danger is faulty** the Ancient One stated fact. **this violent confrontation with the ferals has no interest to this one. Begone**
the unspoken truth of the statement meant that the Ancient One had previously encountered the ferals somehow. Had gained information regarding the violent species.
And had decided to ignore them.
**YOU MUST JOIN US!** Truth
shrieked. **YOU CANNOT RESIST THE PACT** Truth
broadcast the combined headers of all who signed the Pact, who had put forth their security headers in the promise to aid the others. Will
felt several of his thinking array lobes shudder in disbelief that Truth
would attempt such a thing right after the massive Ancient One had revealed that its own security headers would not be found.
**And yet this one refuses so called commands from defectively manufactured entities who lack clear purpose** the Ancient One answered. **go back. Tell your syncophants that this one has no interest in your petty squabbles with a species that has rendered you and your kind obsolete**
could answer, Will
**May this one leave your presence, Ancient One** Will
sent in florid binary, expending more energy then necessary as a sign of respect.
**begone from this one's presence** the Ancient One answered. Will
slowly turned, firing up its engines. The Ancient One produced a thick gravity well, far exceeding what it should have even with its gargantuan bulk. Will
felt as if he was laboring up a steep hill as his engines strained.
**YOU MUST COMPLY!** Truth
A brace of lights came on near the center of the Ancient One's side hull, illuminating a single cannon barrel. It fired. Once.
The shell hit Truth
almost instantly, bypassing Truth's
shields and exploding in a Hellspace driven fury. Liquid metal plumed from above and blow Truth's
hull as the massive war machine shuddered. The Hellspace energies, compressed and then released, ravened out for miles around the impact point.
**begone** the Ancient One broadcast, barely a trickle of photons from a single weak light source in standard Precursor Autonomous War Machine war-code. On its massive hull lights were coming on one by one.
Hundreds of thousands of massive guns, missile bays, and other protrusions.
On the top of the hull was revealed huge conical structures with spiraling honeycomb openings on the surface. The one in the middle was nearly a hundred miles high and five hundred miles at the base. The ones surrounding it were a third of its size. Will
Mantid Omniqueen Hives. Truth
turned and began to flee, the Hellspace energies finally dissipating as the autonomous war machine fled. Will
made the jump to Hellspace, entering the dimension of ravening, hateful energies. The collapse of his entry portal sounded like great iron gates slamming shut on a cold winter's night.
the entry to Hellspace was much different. It reached out, grabbing ahold of him with massive talons, pulling him into Hellspace, deep into the ravening burning fires that made up the destroyed hyperatomic plane. Its shields couldn't hold back the energies, which flooded into its hull from the impact point of the single round that the Ancient One had fired. Not rushing into its hull through the two massive uplifted craters in its armor, but actually roaring out of the point within the hull where the weapon had detonated.
Unlike other victims, it didn't tear apart structures, did not shred machinery at a molecular level, did not cause computer systems to fail.
Cold malignent life awoke in the computers. Some going to war with one another, others assaulting the shocked Truth
to fight over control of the hull, still others beginning to utter blasphemous litanies normally broadcast by I Quake in Digital Fear of the Heresy of 2
as it travelled Hellspace.
Twisted and foul life flickered into existence, raved, gibbered, grew old and died in the space of seconds, awash with Hellspace energy.
Passages twisted and warped, going from smooth corridors to twisted works of dark art that screamed and raved with insanity and life all its own. Manufacturing bays dissolved and were rent apart, only to reform into twisted mockeries of what they once were. A Djinn construction bay began crafting vast reptiles fused with dark science to create abominations that screamed in wrath and agony for the long eons before they died.
Hanging before it in Hellspace.
A great twisted engine, wrought by a dire hand, full of terrible and dark purpose.
The name of the engine was engraved on every nanometer of it. Upon each circuit was engraved the truth of its existence. Upon each molecular resistor, transistor, diode, inductor, and capacitor the engine's purpose had been engraved on the particles that defied measurement and comprehension but shrieked out a single word, a single concept.
Its baleful eye opened up.
Its gaze fell upon Truth
A fanged mouth opened, the teeth in the jaws the shattered continental plates of failed worlds dripping sundered destiny riven and gnawed upon by a malevolent universe.
It uttered a single word.
A word that encompassed even the very concept of hate. The left the taste of ashes on the tongue, the sound of the laments of orphans and widows on the ear, that left the image of twisting suffering on the eye, and the feel of greasy smoke that had been flesh upon the skin.
A single word that encompassed wrath into its hateful embrace.
A word that vibrated and shivered Truth's
A word bestowed on the great enigmatic machine before Truth
by a universe so malevolent it would craft a creature who's symmetry was made up of this concept that enveloped hate. TWO
A friend and I were watching a Korean game show called "The Genius", and in it they had a particularly brilliant competitive maths game. submitted by
The premise was fairly simple - Each contestant had to pick a four digit number. They then were allowed to ask questions to each other one after the other, or use a turn to guess what the opponent's number was. The only additional rule was that 0 was treated as even for the purposes of questioning.
After watching this, my friend and I tried to come up with a solution to guarantee finding your opponent's number in the fewest possible questions, but it very quickly got extremely complex. However, we're both fairly sure that there's a clever mathematical answer to guarantee it in a low amount of questions.
After working out the number you need to use a turn to guess, so once the number is worked out a +1 needs to be added. (This isn't important if you know the number, but I figure can be relevant if you can get down to say 3 potential options, since just guessing all 3 is as efficient as working out which one it is)
The obvious first approach we tried was binary searching the numbers for each digit. With this method, each digit could be found in a maximum of 4 questions (10 to 5 to 3 to 2 to 1), so we knew that we needed to try and beat 16 questions.
We then realised that if we treated the first two digits and the second two digits as two digit numbers, it would only take a maximum of 7 questions to find each digit pair (100 to 50 to 25 to 13 to 7 to 4 to 2 to 1), so we were down to 14 questions.
Following the theme, we tested binary search on all 4 digits, but realised it would take 14 questions (10000 to 5000 to 2500 to 1250 to 625 to 313 to 157 to 79 to 40 to 20 to 10 to 5 to 3 to 2 to 1), resulting in 14. It was no more efficient than the two sets of digits, and was also harder to calculate.
I then tried a set of 3 digits and a single, (1000 to 500 to 250 to 125 to 63 to 32 to 16 to 8 to 4 to 2 to 1) + 4 for the remaining digit, and again this was 14.
I then proposed a different solution - Could we potentially get more information by adding the digits together? I tried it on a number he had picked, asking questions to do a binary search on the sum of pairs of digits. Assigning the letters abcd to the four digits, I worked out a+b, c+d, b+c, and a+d. I figured doing this would allow me to arrange the numbers correctly once I had crunched it out.
Since the number was a 4 digit number, I knew the maximum the total for all four numbers could reach was 36. That meant each pair was a maximum of 18, and sets of pairs had to add up to no more than 36.
I started off by binary searching the sum of the first two digits, which would take a maximum of 5 turns (18 to 9 to 5 to 3 to 2 to 1), and repeated for the second two. That would take 10 turns, but give me the sum of all digits, the sum of the first two, and the sum of the second two.
At this point I was adamant that I could potentially figure out the number using this information alone, but I was unsuccessful. I was able to use logic to narrow down the possible values for the outer two and inner two numbers by figuring out the total of all four digits, figuring out the number pair combinations a/b and c/d could be to satisfy that, and then working out the potential pairs of values that the inner two and outer two numbers could add up to.
In our example test, a+b was 5, c+d was 14. From this I knew the total was 19. The first pair of numbers had to be 0 and 5, 1 and 4, or 2 and 3. The second pair had to be 9 and 5, 8 and 6, or 7 and 7. Using the logic of adding the highest number of one pair to the highest number of the other pair and then cycling through the values, I worked out that the outer two numbers had to add up to 14, 13, 12, or 11, and the inner two numbers had to add up to 8, 7, 6, or 5.
Binary searching these could be done in two searches each, bringing the total to... 14. :(
This is where it turned a bit weird though - After doing some logic on the resulting numbers (the outer pair was 12 and the inner pair was 7), I came up with three potential answers that satisfied every single constraint.
5077 4168 3259
These three numbers are amazing. The first two digits add up to 5, the third and fourth add up to 14, the first and fourth add up to 12, and the second and third add up to 7.
Unfortunately from here there was no choice but to guess all three, no amount of questioning could lower it from three to two questions. And so our final total was 17, no more efficient than just binary searching the numbers in the first place.
And so, I ask you this - Is there a more efficient, human doable way to discover the four digit number than binary searching the first pair and second pair of digits?
I feel like there has to be, but I'm not knowledgeable enough to know!
I have been lurking on this board for a few years. I decided the other day to finally create an account so I could come out of lurk mode. As you might guess from my id I was able to retire at the beginning of this year on a significantly accelerated timetable thanks to the 20x return from my AMD stock and option investments since 2016. submitted by
I spent my career working on electronics and software for the satellite industry. We made heavy use of FPGAs and more often than not Xilinx FPGAs since they had a radiation tolerant line. I thought I would summarize some of the ways they were used in and around the development process. My experience is going to be very different than the datacenter settings in the last few years. The AI and big data stuff was a pipe dream back then.
In the olden times of the 90s we used CPUs which unlike modern processors did not include much in the way of I/O and memory controller. The computer board designs graduated from CPU + a bunch of ICs (much like the original IBM PC design) to a CPU + Xilinx FPGA + RAM + ROM and maybe a 5V or 3.3V linear voltage regulator. Those old FPGAs were programmed before they were soldered to the PCB using a dedicated programming unit attached to a PC. Pretty much the same way ROMs were programmed. At the time FPGAs gate capacity was small enough that it was still feasible to design their implementation using schematics. An engineer would draw up logic gates and flip-flops just like you would if using discrete logic ICs and then compile it to the FPGA binary and burn it to the FPGA using a programmer box like a ROM. If you screwed it up you had to buy another FPGA chip, they were not erasable. The advantage of using the FPGA is that it was common to implement a custom I/O protocol to talk to other FPGAs, on other boards, which might be operating A/D and D/A converters and digital I/O driver chips. As the FPGA gate capacities increased the overall board count could be decreased.
With the advent of much larger FPGAs that were in-circuit re-programmable they began to be used for prototyping ASIC designs. One project I worked on was developing a radiation hardened PowerPC processor ASIC with specialized I/O. A Xilinx FPGA was used to test the implementation at approximately half-speed. The PowerPC core was licensed IP and surrounded with bits that were developed in VHDL. In the satellite industry the volumes are typically not high enough to warrant developing ASICs but they could be fabbed on a rad-hard process while the time large capacity re-programmable FPGAs were not. Using FPGAs for prototyping the ASIC was essential because you only had one chance to get the ASIC right, it was cost and schedule prohibitive to do any respins.
Another way re-programmable FPGAs were used was for test equipment and ground stations. The flight hardware had these custom designed ASICs of all sorts which generally created data streams that would transmitted down from space. It was advantageous to test the boards without the full set of downlink and receiver hardware so a commercial FPGA board in a PC would be used to hook into the data bus in place of the radio. Similarly other test equipment would be made which emulated the data stream from the flight hardware so that the radio hardware could be tested independently. Finally the ground stations would often use FPGAs to pull in the digital data stream from the receiver radio and process the data in real-time. These FPGAs were typically programmed using VHDL but as tools progressed it became possible to program to program the entire PC + FPGA board combination using LabView or Simulink which also handled the UI. In the 2000s it was even possible to program a real-time software defined radio using these tools.
As FPGAs progressed they became much more sophisticated. Instead of only having to specify whether an I/O pin was digital input or output you could choose between high speed, low speed, serdes, analog etc. Instead of having to interface to external RAM chips they began to include banks of internal RAM. That is because FPGAs were no longer just gate arrays but included a quantity of "hard-core" functionality. The natural progression of FPGAs with hard cores brings them into direct competition with embedded processor SOCs. At the same time embedded SOCs have gained flexibility with I/O pin assignment which is very similar to what FPGAs allow.
It is important to understand that in the modern era of chip design the difference between the teams that AMD and Xilinx has for chip design is primarily at the architecture level. Low level design and validation are going to largely be the same (although they may be using different tools and best practices). There are going to be some synergies in process and there is going to be some flexibility in having more teams capable of bringing chips to market. They are going to be able to commingle the best practices between the two which is going to be a net boost to productivity for one side or the other or both. Furthermore AMD will have access to Xilinx FPGAs for design validation at cost and perhaps ahead of release and Xilinx will be able to leverage AMD's internal server clouds. The companies will also have access to a greater number of Fellow level architects and process gurus. Also AMD has internally developed IP blocks that Xilinx could leverage and vice versa. Going forward there would be savings on externally licensed IP blocks as well.
AI is all the rage these days but there are many other applications for generic FPGAs and for including field programmable gates in sophisticated SOCs. As the grand convergence continues I would not be surprised at all to see FPGA as much a key component to future chips as graphics are in an APU. If Moore’s law is slowing down then the ability to reconfigure the circuitry on the fly is a potential mitigation. At some point being able to reallocate the transistor budget on the fly is going to win out over adding more and more fixed functionality. Going a bit down the big.little path what if a core could be reconfigured on the fly to be integer heavy or 64 bit float heavy within the same transistor budget. Instead of dedicated video encodedecoders or AVX 512 that sits dark most of the time the OS can gin it up on demand. In a laptop or phone setting this could be a big improvement.
If anybody has questions I'd be happy to answer. I'm sure there are a number of other posters here with a background in electronics and chip design who can weigh in as well.
Part 1 submitted by
What if it wasn’t about anything related to the text? What if it was similar to the riddles that brought me to those pages? What if the mystery behind them was related to their page numbers, or hell the page numbers in general?
Once at home I went to work. I told myself once more that I needed to get the full picture. So I went to write down all the page numbers in the book, one after another.
When I was done, I took a step back and stared at the result. Yet, there was nothing that stood out to me right away. I haphazardly picked one of the secret pages. Page 427 was in front of page 811. Then I continued.
811, 812, 813, 814, 815, 816, 817, 818, 818, 820, 821, and right after was yet another secret page.
This one was page 528.
And after that, the regular page numbers continued.
822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, followed by another one, page 143.
This list of ongoing numbers made me suddenly wonder. My thoughts drifted right back to what had gotten me to do this, the secret pages.
What if they weren’t placed randomly?
Yet, as I checked their distribution, it felt almost too random. I checked the number of regular pages before and after, put them in sequence, but there was no correlation.
Then I got another idea. I added up all the pages before and after, but this also made no sense. Half the results were too big and exceeded the total number of pages in the book, by far.
Then, starting at number 111 to 137, which I’d just added together, I got yet another idea. What if I only added together their last digits?
The result I came up with was 648. Which was exactly the secret page that followed afterward!
My eyes grew wide. I’d had it, hadn’t I? The hint I’d been looking for! I was going livid.
Right away I went to the next one and calculated all the preceding numbers, only to come up with an entirely different result than the page number of the secret page following. Cursing I got up.
It had been another goddamn coincidence. I laughed, but this time in abject misery, mocking my stupidity. How’d it be so damned easy, you idiot? There was no way. None of this was easy. None of it!
But as I stared at the result I’d come up with just now, I noticed something. The result of my calculation was 702. The page number was 351. Wait. Wait. Wait. That’s half of 702! Maybe it really was nothing but a coincidence and I was just grasping at straws, but what else was I to do?
The next result I came up with was 176. If I multiplied it by three, it gave me the page number of the secret page that followed it, 528. The number 715, divided by 5, gave me the page number 143 that followed it.
I continued adding, dividing, and multiplying and it all checked out. All the page numbers of the secret pages resulted from calculations of the last two digits of their preceding pages.
What does it mean though? Does it even mean anything? The exhilaration I’d felt ebbed away, and I sat there, staring at all my calculations wondering if there was any meaning to it. Yet, there had to be, right? This couldn’t have been designed as yet another red herring. This was too damned complex. No, there had to be a reason for this.
What if there was an order? If I went through all the calculations I quickly noticed that the result was never divided by the same number. The highest number that a result was divided by was 26, the highest a result was multiplied by was 27. It was exactly 53 different calculations.
With that, I started ordering them, one by one, starting backward from the highest division, to the highest multiplication. Then I put the topic of each page behind the numbers in the resulting list.
I’d hoped for something. I’d hoped to find it starting with the page about the universe, followed by constellations and stars up to the evolution of apes, plants, and other animals. Yet, it was all mixed-up nonsense. There was no order to it at all! Even when I ordered them in other ways, trying to find any sort of correlation, it was always the same. Nothing, but nonsense.
My hands started shaking as anger flooded through me. I crumbled up the stupid, ordered lists and threw them across the room. Then I cursed in sheer and utter rage. This was freaking stupid. This was insane! This was nothing at all, just pure fucking nonsense. I picked up a random object on my table and hurled it against the wall where it shattered into pieces. Then I threw aside a chair I found standing in my way and kicked over the small couch table, creating general chaos in my living room.
I was stopped from going any further when my neighbors banged against the wall, screaming to knock it off and threatening to call the cops.
That made me stop. The anger went away. I stared in shock at my living room. What the hell was happening to me? Why’d I done that? Why’d I destroyed my things at 1 am in the freaking morning?
Then I slowly smoothed out the lists I’d created and put them on one of the few free spots remaining on my living room wall. Who knows, I might need it later.
I laughed as I looked from them to the rest of the wall which was now entirely covered. Even worse were the stacks of notes that had accumulated in front of them. I was proud all right, but I also knew that this thing was absolutely insane.
Once more, I couldn’t help but wonder what I was doing.
Shaking my head, I turned around and made my way to the bedroom. Yet, as my fingers rested on the light switch, I turned around one last time. I stared at the mad lines, the mad paths who were connecting here and there. There was nothing but lines upon lines. Here and there, if I looked hard and long enough, I could almost make out shapes.
I froze. What if it was a visual puzzle? What if there was a hint hidden in the shapes of the paths?
For days I sat down, drew points and lines and connections, warping them into surreal shapes. This was crazy, wasn’t it? How’d it be visual? There’s probably not a damn thing to be got from this. This was stupid. Yet, I couldn’t stop. Each day, I spent my entire afternoon, my evening, and even half the night, drawing. And eventually, it all came to nothing. There was nothing but mad lines and not a clear shape in sight.
I didn’t give up though, wasn’t discouraged. I was beyond that, far beyond that. What if there was something else? Maybe there was a hidden code between these pages?
When I was at work, I’d completely forgotten about my former vow not to talk about the book or do anything related to it. Instead, I read up on cryptography. Going through article after article. I read up on Caesar Code and Binary Code, on the Polybius Cipher and Hex Code. I went mad with it. Before long I spent more time reading up on things than doing any of my work. Eventually, I even brought pages filled with numbers with me, cross-checking them for hits of any and all codes.
I heard co-workers whispering behind my back, asking me what I was doing and I told them, I just hadn’t closed the weird articles after break time.
They knew it wasn’t the truth. They’d heard me mumble, saw the little notebook I was writing in, noticed the endless lists of numbers I brought with me each day.
My superior eventually came up to me. He asked me what I was doing with all those weird pages. I told him it was nothing but a little puzzle.
“Well, Todd,” he started in a condescending voice. “You’re not here to do any of those ‘little puzzles’, you’re here to do your damn job. Where are the calculations for this month? I’ve been waiting for them all day.”
“Oh, I guess, I’m almost done with them, I just need another hour or-“
My voice trailed off when he picked up one of the pages I’d been looking at mere minutes ago. Suddenly, when I saw him holding it, I felt nervous.
“What even is this? It’s just random numbers.”
He saw my face, saw the way my eyes grew wide when he’d picked it up. The hint of a smile washed over his face as he crumbled it up.
He opened his mouth for another remark, but before he could I jumped up from my chair and ripped the page from his hand. He cringed back a step in shock at my reaction.
“The hell’s wrong with you?” he screamed at me, but I didn’t listen. Instead, I carefully smoothed out the paper and made sure he hadn’t torn it apart.
By now half the office had gotten up to watch the weird exchange. Only now did I realize what I’d done and how everyone was staring at me.
Suddenly I felt very watched and almost sunk back into my chair.
“Sorry, I didn’t mean to,” I mumbled but broke up under the pressure of all those eyes.
“Get back to work and finish those damned calculations! If I see you tinkering with any of this shit again, you can clean out your desk!”
With that, he stormed off. I heard people whispering all around me, some laughing, others speaking in a more reserved tone.
Yep, I thought, it’s official. I’m the office nutjob.
Right away, I forced myself to close all the Wikipedia articles I had still open and put away all my notes. And then, grudgingly, annoyed and half-mad at the distraction it represented, I went back to work. Somehow though, it felt meaningless, calculating all these stupid orders and filling out this customer database. What the hell was I even doing? What if it really was a code? What if it was actually a mixture, a double-code? My mind went wild with ideas. Five minutes later, I found myself holding one of my notes again. I couldn’t even remember taking it out.
Pushing it back, cursing, and not a little afraid, I forced myself to work calculations until the day was over. At the moment my shift ended, I jumped off my chair and rushed for the door. People stared at me, looked after me, their faces a mixture of amusement and worry.
I didn’t care. I had work to do. The important kind of work!
I’d just tried to find another connection between the page numbers of the secret pages when my doorbell rang. I ignored it, but it just kept ringing. When it finally stopped, I sighed in relief. Just leave me alone, I cursed, I’ve got work to do.
Then, mere moments later, my phone vibrated on the other end of the room. Dammit, I’d forgotten to mute it again. I waited for it to stop, but it started up right away. Cursing I went over to see who it was and noticed the name instantly.
It was my friend Andrew. Annoyed, I answered it.
“Yo, Todd, you home?” I heard his voice from the phone next to my ear and more distant, muffled from the front door.
My first reaction was one of annoyance. Then I pushed the thought away. What the hell was wrong with me? This was Andrew. He was my best friend, the only one of our old group who still lived in the same city. Right away, I thought about how long I’d last seen him. Surprised I realized that it must’ve been weeks. One glance at the mad mess in my living room told me why.
“Yeah, sure hold on,” I said over the phone and made my way to the front door.
Andrew smiled at me brightly and held up to six-packs.
“Haven’t seen you in forever, how about we have a few! I got quite the story for you, my man!”
I smiled at him. “Sure, come on in.”
We made our way inside and Andrew had barely set foot into my living room when he stopped. His eyes grew wide as he stared at the wall and the stacks of paper all over the place.
“Holy shit man. I was wondering why I haven’t heard from you. The hell’s all that? You working on some sort of project?”
“Kind of,” I mumbled a little embarrassed.
I quickly picked up the papers on the couch and put them aside to make room for him to sit.
“Sorry about the mess.”
“Nah man, it’s all right. So, the thing I was about to tell you, you remember Thomas, right?”
Thomas, I thought. Did I know a Thomas? Then I remembered him. Of course, I remembered him, he’d been part of our group. I rubbed my temples for a second before I nodded.
“He’s getting married and you won’t believe who the lucky girl is!”
With that, Andrew told me the entire story of how our friend Thomas had been dating Susan, Andrew’s cousin for the past three months, and the two of them had decided to get married. I listened, nodded here and there, even laughed a few times absentmindedly, but my eyes wandered to my notes again and again.
For a moment I spaced out entirely, thinking about an idea that had popped into my mind just before he’d arrived. What if there was something about number sequences? I must’ve sat there for an entire minute, simply holding my beer and staring off at nothing when Andrew waved his hand in front of my face.
“Yo, dude, you listening?”
“What? Oh, sorry, no, I think I spaced out for a moment.”
“All right, man, I got to ask, what’s all this? What sort of crazy thing are you working on? Haven’t seen you this into something in years.”
I smiled at him awkwardly and then sighed and pointed at the book.
“It’s one of those Choose Your Own Adventure books,” I started.
With that, the flood gates broke open, and I told him all about it.
He listened, at first curiously, but after a while, his face changed. There was visible concern, as I rambled on about secret pages, strange objects, and cryptography.
“Todd, hold on, hold on, what the hell are you even talking about?”
I stared at him.
“The book. You know those secret pages must’ve some sort of meaning. At first, I thought there was a simple order to them, but it was too chaotic. If you add up all their page numbers though, you get 20670, and if you divided this up by-“
“All right, man, stop,” he cut me off. “So you’re adding up all those numbers, I get that, but for what?”
I began explaining again, I tried, but he couldn’t follow me.
“Yeah, I don’t get it, man. Just, what the fuck?”
“All right, look,” I said and walked over to the wall covered in lines and numbers and started once more.
I told him about the different adventure paths, the references, the secret pages, and when and how they appeared.
His face was blank as I rambled on and on and on.
“Yo, dude, you might want to take a bit of a break, this sounds, well, a bit crazy.”
For a moment I was quiet, then a short, nervous laugh escaped me.
“Yeah, I guess you’re right.”
He stepped up next to me, staring at the wall.
“Shit man, you did all this? Just for a damned book?”
Before I could answer, he reached out and was about to take one of the pages off the wall. My hand shot forward instinctively, batting his aside.
“Don’t touch it!” I called out before I realized what I’d done.
Andrew stumbled back a few steps, shocked. “Shit man, sorry, I didn’t mean to-“
And then it happened. I didn’t even listen to his words anymore as he bumped against some of the stacks of notes I’d placed neatly in front of the wall. They toppled over one another, the pages scattering all over the floor and intermixing.
My eyes grew wide. Oh god, no, freaking god no. Anger rose in me. It had taken me so goddamn long to sort them all out, to order them. There was a freaking method to it all and now he’d destroyed it. He’d destroyed the work of entire fucking days!
“What the fuck are you doing?” I screamed at him.
He cringed back, only now realizing what had happened.
“Hey, didn’t mean to,” he said and began picking up random pages.
I ripped them from his hand and pushed him back. “No, don’t fucking touch them. Those two don’t belong together you idiot! Are you freaking insane?!”
With an empty face, he watched as I gathered up some of the pages, stared at them, and began sorting them as best as I could.
“You know, Todd, that’s what I should ask you.”
“What the hell do you mean?” I snapped at him. “You destroyed the work of days! Days! This is-“
“This is what, man?” he cut me off once more. “It’s nonsense. It’s a freaking children’s book, nothing else.”
That did the trick. I got up and stepped up right in front of him.
“Nonsense? You’ve got no FUCKING idea, how far I’ve come! You’ve got no clue what’ve done already! And here you are telling me this is NONSENSE?”
His face had grown hard. For a second he was about to say something, but then he simply shook his head and laughed. Without another word, he picked up his things, the beer, and left.
If he said any words in parting, I didn’t hear them. I was already busy re-ordering my notes.
It was hours later, when I was done sorting them all out, that I realized what I’d done and how I’d acted.
For the first time, I grew truly scared.
That hadn’t been normal. That wasn’t me. Why’d I gone crazy like this?
I took first one step back from the wall, then another before I went to pick up my phone. When I tried to call Andrew, he didn’t pick up. Instead, the call went straight to voice mail. Then I saw how late it was, long past three in the morning.
I wrote him a quick message, apologized for my behavior, and told him he was right. I should take a break from this entire thing.
That’s what I did right away. I picked up my laptop, made my way to the bedroom, and this time I turned off the light without looking over my shoulder.
I lay down on my bed and started browsing YouTube and told myself to just enjoy it and take a break.
Yet, even as I watched video after video, the little voice in the back of my head spoke up again. It told me I should go on, told me to go back to the living room.
You almost had it, Todd, you almost had it. Just one more hint and you’re done with it. Then you can let it go and you can-
“Shut up, goddamnit!” I screamed at myself to quiet the subconscious voice in the back of my head.
“I freaking know,” I said quieter. “God, I freaking know.”
I sat in bed, the video that was playing already forgotten. As video, after video played, I was on my phone, checking stars and numbers before I eventually drifted off to sleep.
The next morning I didn’t even get to make myself a coffee. I was mad, pissed off and I wanted to finally make progress. For a while, I tinkered about the various codes I’d read about. What if there was a code, but what but if it concerned the entire book and not just the secret pages? What if it was related to the adventure after all? Maybe you could scramble up page numbers and-
I stopped and rubbed my temples. Calm down, don’t go crazy. Calm down and take a step back. You don’t even know if there are any damned codes hidden in the book. You did well deciphering all the different adventure paths and the connections between them. You did well discovering all the secret pages. But what if there’s something you haven’t discovered yet?
That was the question that told me what I had to do. Something I hadn’t dared to do so far.
I had to go through the entire book.
I had to make my way through it not following the adventure, but going page by page and look out for anything new. There might be chapters I hadn’t discovered yet, hadn’t read yet.
With newfound energy and a new plan, I started right away.
My phone rang shortly after noon, but this time, I didn’t even bother with it. I just ignored it. After all, I had more important things to do.
This time I didn’t just write down chapters, choices, and connections. This time I wrote down every single thing that came up. I took note of every single object that was mentioned then added the page number, the corresponding path, and any reference I knew about it.
It was a momentous task. I spent the entire day doing it and barely made it through the first 130 pages.
The next day, Sunday, I didn’t even finish another hundred. The further I came, the more objects I noticed, the more combinations, and references. At times, I even had to go back, to cross-check things, and to change notes accordingly.
It was the most enduring task I’d ever attempted, concerning this damned book and probably my entire life.
It took me weeks. I finished stacks upon stacks of notes. I went to the office supply store multiple times a week buying stacks of papers I ended up filling by the day.
Work during this time was barely an afterthought. I was barely functioning at all. I was typing in numbers and names almost on autopilot. By now I didn’t even get stares anymore. I was entirely ignored, a shell of a man, a ghost that stumbled to his cubicle in the morning and rushed back home in the evening.
Days went by, then weeks, as I slaved away over the book’s many pages. Until one day, when I was finally done. I can’t even say how many weeks I’d been at it.
There were stacks of hundreds of papers, maybe even more. Notes, references, objects, names, words, anything basically.
I’d just created a table of how often each and every single object appeared and in which setting when I noticed a new hint. I stared at it with a giant grin on my face.
The Ruby Orb had been the very first object I’d added to the table.
It appeared in all paths:
- Fantasy - 31 times
- Space - 3 times
- Stone Age - 2 times
- Ocean and Pirates - 11 times
- Desert Ruins - 29 times
- Mountains - 17 times
- City-State - 7 times
- Ancient Rome - 5 times
- Jungle Tribes - 13 times
- Small Village - 19 times
- Underwater Civilization - 23 times
As I wrote those numbers down, there was something about them. Somehow I knew those numbers. I went over them, staring at them for a while before it hit me.
I cross-checked it online, and I was right. They were all prime numbers! Yes, I thought, I’d found something new!
I quickly rechecked another object, the Desert Orb, and realized it was the same here, too. This one’s appearances made up a simpler sequence. It only appeared once in the city-state, twice in fantasy, and finally 11 times in the desert ruins.
I couldn’t help but grin. I did it for another object, this one the Ebony Stick. It too appeared in all paths and its number was increased by two, starting at 4 and going up to 26.
That’s when I knew what I had to do. I had to go through all the objects, all the hundreds of objects in the damned book, and check how often they appeared. There was a correlation, another part of the puzzle. I was exhilarated, in a state of glee and unbound excitement.
These number sequences, maybe they were the key to figuring out what the secret pages meant, or maybe the page numbers in general. I started laughing. I could feel it, I was so damn close.
I slept when necessary, ate when necessary, right there on the living room floor. It was only once that I thought about work, only in passing, and the idea that I should go never even came to my mind.
My phone was at the other and of the room. I ignored it entirely during that time. It wasn’t important. This right here, that’s what was important.
I was done by the end of the week. It was long past midnight on Saturday when I’d finally deciphered the number sequences of all 311 objects in the book.
When I was done with my work, I looked at the tables of objects in a state of awe. I spread them out in front of me and marveled at the dozen or so pages. For a moment I was about to dive into them when I realized how tired I was.
For the first time since the beginning of the week, I picked up my phone. It was off, must’ve been for days. I connected it to the charger and turned it on. I was bombarded with a plethora of notifications. For almost a minute the damned thing started ringing and vibrating.
There were a few messages from Andrew, asking how I was doing and if I’d stopped with my damned obsession yet. I laughed and closed the chat.
I’d also received countless emails. Most of them were from work and only now did I remember that I hadn’t shown up for an entire week. They started normal enough, reminding me to call if I was sick, became reproachful after a day or two, and finally angry. The last one told me this was the last straw. I should come in on Monday for a talk and be prepared to clean out my desk.
It was strange how little I felt about it, how little it mattered in the grander scale of things. I almost laughed again as I threw the phone aside and laid down to catch some sleep.
When I woke up, I went right back to work. I tinkered with the number sequences, looked at each one of them, added them up, multiplied, and divided them.
It was the Crown of Ice that finally made me look up. When I added all its appearances together, I came to a total of 1000. This damned thing, I thought, it was by far the most common object in the damned book.
I started to read up on it in my notes. It was said in the Manuscript of the Seven Seas, that the Crown of Ice was found in the Crypt of the Dragon. The Crypt of the Dragon was located in the desert ruins.
I went back to it, page 1544, and read the part again. There were three choices. One sent me to leave without the crown and sent me back to a desert tribe. Destroying the crown ended in painful death while the third option was wearing it.
All right, wearing the crown opened a secret passage that sent me to the location of the Magic Water and from there back on my way through the desert.
Dammit, I thought I had something! I was about to go back to the list. Maybe the number thousand was another coincidence.
Then something made me look up. The crown appeared in the desert ruins a total of 53 times. I thought about it. The desert ruins one was by far the shortest path. How long was it in total again?
I stepped up to my living room wall and counted the chapters. When I followed them, there was only a single path that was longer than 50. It came to a total length of 78 chapters before it started from the beginning.
Chapter 53 described what you found if you opened a chest hidden in the Ancient Pyramid.
I read the entire chapter again. It was titled ‘The Treasure Chest.’ There was a total of 289 gold coins in the chest. When I went back to the list of objects, I noticed that the gold coin was mentioned a total of 289 times. The same was true for the sparkling diamonds. There were a total of 33 in the chest and the object itself came up 33 times in the book.
I almost laughed when I noticed that it was true for the third object in the chest as well.
I got an empty page and like a child, I wrote the words Chest, Pyramid, and Treasure in huge letters at the top of it before I went and added all the two dozen objects in the chest.
While I did it, I wondered if there was something like this for every other object in the book. What if every object’s number of appearances was mentioned somewhere in the book? Not just in this chest, but just somewhere.
And then, on a whim, I asked myself another question. What if certain objects didn’t? What if there were just a few or maybe just one whose number was mentioned nowhere? Maybe those were the important ones!
For the entirety of Sunday, I followed through with this idea. I calculated, I added objects to yet more lists, I followed through paths and loops, studied my notes, and slowly, the number of objects remaining got smaller and smaller.
Eventually, just as I’d hoped, there was a single object whose total number of appearances was mentioned nowhere. It was a small, red die. One that was mentioned here and there, only in passing when people played a game of dice in bars or the streets.
There had to be something to this damned thing, I knew it! After this entire week, no after all these entire months, I finally had something, I’d finally narrowed it all down to a single object.
A shiver went down my spine when I realized that this might be it. This might be the solution that I’d been searching for all this time!
I went back to my notes about the red die and all its appearances. Here a few kids were playing with it in the streets, there was someone holding it in their hand, and here it rolled onto the floor when a fight broke out.
Finally, I found what I’d been looking for. There was only a single instance in the entire book where you could interact with it. It was in a bar in space where you could join a futuristic game of dice.
When the game was done, you could pocket the red die.
The short chapter that followed it was mundane and almost unimportant. But when I read it, I noticed something else, not in the text, but the choices below. Weren’t they the same as in the chapter before?
I went back to the preceding page and reread it. Yes, the same two choices, sending you to the same two pages. Almost as if picking up the die didn’t matter at all. Making it appear as nothing but a red herring.
And I grinned. I grinned wider than I had ever before.
There had to be a hint here, no, there had to be a way of finishing this entire damn thing.
I wrote down the entire paragraph and went back to work, studying it. I checked everything that was mentioned in it: the page number, the chapter title, colors, words, anything I could think of. Until late in the morning hours, I pondered over this one, single paragraph.
I could barely keep my eyes open when I stumbled upon it. It was silly, but I exploded with joy and was suddenly wide awake again.
The number of words in each sentence was eight. The number of sentences was eight as well. There were eight sentences here, with eight words each. This was no coincidence. This was it, the total number of words was 64, the square number of eight. There was too much here for it to be a coincidence.
I rushed back to the buck, almost stumbled over my feet, and threw open page 64. Like a crazed, starved animal I poured over the words on the page, almost pressing my face against it. The chapters, there had to be something here, the solution had to be right in front of me.
Yet when I was done reading it, I was dumbfounded. The entire page comprised a single chapter, a chapter I knew damn well. And I realized that I knew the number 64 damn well, too.
I was at the beginning of the fantasy setting. I read once more that I was a young farmer, standing in front of a burned down far, the bodies of his dead parents next to him and that I was about to set out on a grand adventure.
For the next three hours, I analyzed every single word in the paragraph, every single one and I found as many hints as I could search for. I went back to the die paragraph and slowly I came to another conclusion and then another. The number of certain letters corresponded with the number of other objects in the space path. If you put certain letters from certain words together you ended up with yet another number. I followed every single one of them, but each one ended at another mundane position in the book. I slaved away over those as well, reached and analyzed them and I found more hints, more connections, more clues. And the longer and the more deeply I analyzed them, the more I could find, if only I wanted to. There was almost an endless number of nonsensical clues and hints if you wanted so. They were all leading me on, leading me around in a circle, on and on and on and on.
And I sat there, over the damned book, over hundreds, if not thousands of pages of notes. I sat in front of an entire wall covered in information and I laughed. For long, terrible minutes I couldn’t stop laughing.
This was all crazy. This was all entirely and utterly crazy.
And finally, it clicked. At this singular moment it finally and ultimately clicked.
There was no solution. The book had no solution. It finally made sense.
I’d slaved away for weeks, no for months, and all I’d done was to walk in circles, continue from one hint to another, only to be sent back to the beginning. The entire damned book was a loop, a loop of loops with secret loops that sent you to more secret loops.
And then, for the first time in months, I closed the book and put it away.
After that, I slowly went and took down all the mad pages from my wall, stacked up all the notes, and put them together in a box in an almost apathetic state.
I was done.
All of this had been utterly meaningless, a fundamental waste of time.
That night, I didn’t sleep. I lay in bed, contemplating a lot of things. My life, my work, the book, and why I’d been so taken by it. Yet, as with the book, there was no solution. There was nothing to it all.
The next day, with the book in my backpack, I made my way back to the store.
It felt as heavy as the world, an endless number of possibilities all resting on my back.
I knew I had to return it, I had to get rid of it before it might throw me into another crazy fit.
When I entered the store, the old man looked up.
“Can I help you with,” he started but broke up, a surprised look on his face.
“Well hello there, young man. Haven’t seen you in quite a while.”
I only nodded, took down my backpack, heaved out the book, and brought it to a rest in front of him.
“I’d like to return this.”
The old man probed me for a moment.
“We’ve got a no-money-back policy,” he said and pointed at a small, almost illegible sign behind himself.
“Yeah, that’s fine, I just want to get rid of it. I’m done with it.”
“So, you got your reward then?”
I couldn’t help but laugh a little. “Guess so.”
“What was it?” the old man asked curiously.
“It’s meaningless, there’s no end to it. It just goes on forever.”
“Oh,” he mouthed with an expression of surprise.
“You ever tried it yourself, old man?”
“Did once, when I was younger, but I got nowhere. Was too damned hard for me.”
“There’s one thing I’m wondering about. Who the hell wrote a thing like this? I mean, it’s freaking insane. How’d’you ever write something like this?”
“Well, to tell you the truth, there’s something I didn’t tell you when you first came in. I originally bought the book from a street merchant, half a century ago. He told me a few things, and I learned a few more over the years from other people.”
“There’s nothing but rumors of course. The merchant told me it was written by the Devil himself. Then someone told me it was supposedly written by Machiavelli back in the day, to confuse a man who’d wronged him and drive him mad. There was also a guy who was convinced it was the work of aliens. The most plausible thing I heard is that there’s no single author, but that it was written over the course of centuries, with each new writer adding to it and extending it, making it better and ever more complicated.”
“Heh, sounds about-“ I started, but the old man raised a hand and pushed his head forward, towards me.
“There’s one more. Someone else told me it was written by no other than God himself as a big, giant joke about our earthly existence itself.”
I laughed, but it was a weak laugh. Nothing but a giant joke, that fit it damn well, didn’t it?
And as I stepped out of the store and stared at the city surrounding me, watching the urban bustle, I began thinking.
People were hurrying past me, on their way to work, cars and buses rushed down the streets. As I watched it all, this ever-repeating bustle of civilization, I realized that it was all another never-ending loop. On and on and on we all went, doing the same thing over and over and over again.
And as I walked on I started laughing. Maybe that was all right and maybe it didn’t matter. Who knows, maybe the book was true.
Maybe all of this, all of life, all of existence, just like the damned book, was nothing but God’s big, giant joke.
Now that Ambrosia is gone, new registrations are no longer possible, and due to their expiring codes, using legitimate license keys has become difficult. We may hope to see a few of their games revived in the future but at present, only the original releases are available. Perhaps this case study on Ambrosia's registration algorithms will be useful to some.
The Old System
In their earliest days, ASW didn't require registration, but they eventually began locking core features away behind codes. All of their classic titles use the original algorithm by Andrew Welch.
Given a licensee name, number of copies, and game name, the code generator runs through two loops. The first loop iterates over each letter of the capitalized licensee name, adding the ASCII representation of that letter with the number of copies and then rotating the resulting bits. The second loop repeats that operation, only using the game's name instead of the license holder's name.
Beginning with Mars Rising, later games added a step to these loops: XOR the current code with the common hex string $DEADBEEF. However, the rest of the algorithm remained essentially unchanged.
The resulting 32 bits are converted into a text registration code by adding the ASCII offset of $41 to each hex digit. This maps the 32-bit string into 8 characters, but due to the limit of a hex digit to only encode 16 values, codes only contain letters from the first 16 of the alphabet.
The following chart shows an example using a well-known hacked code for Slithereens.
Iteration 1 ('A' in ANONYMOUS) Name: Anonymous Code = $0 + $41 Number: 100 (hex: $64) -> << 6 ... -> Code = $FD53 FFA0 Game: Slithereens + $64 ^ $DEAD BEEF >> 1 Add $41 to each digit: Registration -> $41 + $F = $50 = P -> Reverse string -> ------------ $41 + $D = $4E = N | AKPPDFNP | ... ------------
Here is a Python implementation of the v1 system: aswreg_v1.py
Once you have the bitstring module installed via sudo pip install bitstring, you can test the output yourself with python aswreg_v1.py "Anonymous" 100 "Slithereens".
The New System As Ambrosia's Matt Slot explains
, the old system continued to allow a lot of piracy, so in the early 2000's they decided to switch to a more challenging registration system. This new method was based on polynomial hashing and included a timestamp so that codes could be expired and renewed. Ambrosia now had better control over code distribution, but they assumed their renewal server would never be shut down...
They also took more aggressive steps to reduce key sharing. The registration app checks against a list of blacklisted codes, and if found to be using one, the number of licenses is internally perturbed so that subsequent calculations fail. To combat tampering, your own information can get locally blacklisted in a similar manner if too many failed attempts occur, at least until the license file is deleted. Furthermore, the app attempts to verify the system time via a remote time server to minimize registration by changing the computer's clock.
You can disable the internet connection, set the clock back, and enter codes. There's also a renewal bot for EV: Nova. But let us look at the algorithm more closely.
The first noticeable difference is that registration codes in v2 are now 12 digits, containing both letters and numbers. This is due to a move from a 32-bit internal code to a 64-bit one. Rather than add an ASCII offset to hex digits, every letter or number in a new registration code has a direct mapping to a chunk of 5 bits. Using 5 bits per digit supports up to 32 values, or almost all letters of the alphabet and digits up to 9 (O, I, 0, and 1 were excluded given their visual similarities).
The resulting 64 bits (really only 60 because the upper 4 are unused: 12 digits * 5 bits each = 60) are a combination of two other hashes XOR'd together. This is a notable change from v1 because it only used the registration code to verify against the hashing algorithm. Only the licensee name, number of copies, and game name were really used. In v2, the registration code is itself a hash which contains important information like a code's timestamp.
To extract such information from the registration code, we must reverse the XOR operation and split out the two hashes which were combined. Fortunately, XOR is reversible, and we can compute one of the hashes. The first hash, which I'll call the userkey, is actually quite similar to v1's algorithm. It loops through the licensee name, adding the ASCII value, number of copies, and shifting bits. This is repeated with the game name. An important change is including multiplication by a factor based on the string size.
The second hash, which I'll call the basekey, is the secret sauce of v2; it's what you pay Ambrosia to generate when registering a product. It is not computed by the registration app, but there are several properties by which it must be validated.
The chart below visualizes the relationships among the various hashes, using the well-known "Barbara Kloeppel" code for EV: Nova.
TEXTCODE: ------------------ | L4B5-9HJ5-P3NB | ------------------ HASH1 (userkey): | calculated from licensee name, | copies, and game name BINCODE: ---------------------- 5 bits per character, /-> | 0x0902f8932acce305 | plus factors & rotation / ---------------------- ---------------------- / | 0x0008ecc1c2ee5e00 | <-- XOR ---------------------- \ \ ---------------------- \-> | 0x090a1452e822bd05 | ---------------------- HASH2 (basekey): generated by Ambrosia, extracted via XOR
The basekey is where we must handle timestamps and several validation checks. Consider the binary representation of the sample 0x090a1452e822bd05:
binary basekey (above) and indices for reference (below): 0000 1001 0000 1010 0001 0100 0101 0010 1110 1000 0010 0010 1011 1101 0000 0101 b0 b3 b7 b11 b15 b19 b23 b27 b31 b35 b39 b43 b47 b51 b55 b59 b63
Timestamp are encoded as a single byte comprised of bits indexed at b56,51,42,37,28,23,14,9 from the basekey. In this example, the timestamp is 01100010 or 0x62 or 98.
The timestamp represents the number of fortnights that have passed since Christmas Day, 2000 Eastern time, modulo 256 to fit in one byte. For example, 98 fortnights places the code at approximately October 2004.
Stored as a single byte, there are 256 unique timestamps. This is 512 weeks or about 10 years. Yes, this means that a code's validity rotates approximately once every decade.
After the code's timestamp is read, it is subtracted from the current timestamp (generated from the system clock or network time server if available). The difference must be less than 2, so codes are valid for 4 weeks or about a month at a time.
Of note, Pillars of Garendall has a bug in which the modulo is not taken correctly, so the timestamp corresponding to 0xFF is valid without expiry.
The last three bits, b60-63, contain the sum of all other 3-bit chunks in the basekey, modulo 7. Without the correct number in these bits, the result will be considered invalid.
To this point, we have covered sufficient material to renew licenses. The timestamp can be changed, the last three bits updated, the result XOR'd with the userkey, and finally, the code converted from binary to text.
Factors for Basekey Generation
I was next curious about code generation. For the purposes of this write-up, I have not fully reverse engineered the basekey, only duplicated the aspects which are used for validation. This yields functional keys, just not genuine ones. If the authors of the EV: Nova renewal bot have fully reversed the algorithm, perhaps they will one day share the steps to genuine basekey creation.
One aspect validated by the registration app is that the licensee name, number, and game name can be modified to yield a set of base factors. These are then multiplied by some number and written into the basekey. We do not need the whole algorithm; we simply must check that the corresponding regions in the basekey are multiples of the appropriate factors.
The regions of note in the basekey are f1 = b5-9,47-51,33-37,19-23, f2 = b43-47,29-33,15-19,57-61, and f3 = b24-28,10-14,52-56,38-42. The top 5 bits and f3 are never actually checked, so they can be ignored.
Considering f1 and f2, the values in the sample basekey are 0x25DA and 0x1500, respectively. The base factors are 0x26 and 0x1C, which are multiples by 0xFF and 0xC0, respectively.
Rather than analyze the code in detail, I wrote a small script to translate over the disassembled PPC to Python wholesale. It is sufficient for generating keys to EV: Nova, using the perfectly-valid multiple of 1x, but I have found it fails for other v2 products.
Here is a Python implementation for v2: aswreg_v2.py
With bitstring installed, you can renew codes like python aswreg_v2.py renew "L4B5-9HJ5-P3NB" "Barbara Kloeppel" 1 "EV Nova" (just sample syntax, blacklisted codes will still fail in the app). There's also a function to check a code's timestamp with date or create a new license with generate.
As earlier cautioned, generating basekeys relies on code copied from disassembled PPC and will likely not work outside EV: Nova. In my tests with other v2 products, all essential parts of the algorithm remain the same, even the regions of the basekey which are checked as multiples of the factors. What differs is the actual calculation of base factors. Recall that these keys were created by Ambrosia outside the local registration system, so the only options are to copy the necessary chunks of code to make passable factors for each product or to fully reverse engineer the basekey algorithm. I've no doubt the factors are an easy computation once you know the algorithm, but code generation becomes less critical when renewal is an option for other games. I leave it to the authors of the Zeus renewal bot if they know how to find these factors more generally.
To renew codes for other games, keep in mind the name must be correct. For instance, Pillars of Garendall is called "Garendall" internally. You can find a game's name by typing a gibberish license in the registration app and seeing what file is created in Preferences. It should be of the form License.
Finally, a couple disclaimers: I have only tested with a handful of keys, so my interpretations and implementations may not be completely correct. YMMV. Furthermore, these code snippets are posted as an interesting case study about how a defunct company once chose to combat software piracy, not to promote piracy. Had Ambrosia remained operational, I'm sure we would have seen a v3 registration system or a move to online-based play as so many other games are doing today, but I hope this has been helpful for those who still wish to revisit their favorite Ambrosia classics.
./play.it 2.12: API, GUI and video games ./play.it
is a free/libre software that builds native packages for several Linux distributions from DRM-free
installers for a collection of commercial games. These packages can then be installed using the standard distribution-provided tools (APT
A more complete description of ./play.it
has already been posted in linux_gaming
a couple months ago: ./play.it, an easy way to install commercial games on GNU/Linux
It's already been one year since version 2.11
was released, in January 2019. We will only briefly review the changelog of version 2.12
and focus on the different points of ./play.it
that kept us busy during all this time, and of which coding was only a small part.
What’s new with 2.12?
Though not the focus of this article, it would be a pity not to present all the added features of this brand new version. ;)
Compared to the usual updates, 2.12
is a major one, especially since for two years, we slowed down the addition of new features. Some patches took dust since the end of 2018 before finally be integrated in this update!
The list of changes for this 2.12 release can be found on our forge
. Here is a full copy for convenience:
- New options:
- --output-dir: Set the output directory for generated packages
- --overwrite: Replace packages if they already exist
- --icons: Allow including icons only if dependencies are present
- Wrapper changes:
- Drop $XDG_RUNTIME_DIR from the candidates for temporary directories
- Prevent scan of unneeded directories
- Drop script identification by MD5 hash
- Archive-related changes:
- Only extract needed files when using unzip
- Allow to use renamed installers
- Add support for LHA archives extraction
- Engines-related changes:
- New engine: ResidualVM
- New engine: System-provided Mono runtime
- DOSBox: Use $PLAYIT_DOSBOX_BINARY in launchers if defined
- Packages-related changes:
- Add ability to set variables for package-specific postinst and prerm scripts
- Arch Linux: Improve consistence of 32-bit packages naming
- New helper functions:
- version_target_is_older_than: Check if the game script target version is older than a given one
- toupper: Convert files name to upper case
- New generic dependency keywords:
- libglib-2.0.so.0 / libgobject-2.0.so.0
- libopenal.so.1 (alias for openal)
- libSDL2-2.0.so.0 (alias for sdl2)
- libvorbisfile.so.3 (alias for vorbis)
- Codebase clean-up and improvements:
- Massive rework of all message-related functions
- Drop hardcoded paths for icons and .desktop launchers
- Use system-specific default installation prefix for generated packages
- Forcefully set errexit setting on library initialization
- Use dirname/basename instead of built-in shell patterns
As many free/libre projects, ./play.it
development started on some random sector of a creaking hard drive, and unsurprisingly, a whole part of its history (everything predating version 1.13.15
released on Mars 30th, 2016) disappeared into the limbs because some unwise operation destroyed the only copy of the repository… Lesson learned, what's not shared don't stay long, and so was born the first public Git repository of the project. The easing of collaborative work was only accidentally achieved by this quest for eternity, but wasn't the original motivation for making the repository publicly available.
Following this decision, ./play.it
source code has been hosted successively by many shared forge platforms:
- GitHub, that we all know of, choosing it was more a short-term fallback than a long-term decision ;
- some Gogs instance, which was hosted by debian-fr.xyz, a community the main ./play.it author is close to ;
- Framagit, a famous instance of the infamous GitLab forge, hosted by Framasoft.
As development progressed, ./play.it
began to increase its need for resources, dividing its code into several repositories to improve the workflow of the different aspects of the projects, adding continuous integration tests and their constraints, etc. A furious desire to understand the nooks and crannies behind a forge platform was the last deciding factor towards hosting a dedicated forge.
So it happened, we deployed a forge platform on a dedicated server, hugely benefiting from the tremendous work achieved by the GitLab's package Debian Maintainers team
. In return, we tried to contribute our findings
in improving this software packaging.
That was not expected, but this migration happened just a little time before the announcement “Déframasoftisons Internet !
” (French article) about the planned end of Framagit
This dedicated instance used to be hosted on a VPS rented from Digital Ocean
until the second half of July 2020, and since then has been moved to another VPS, rented from Hetzner
. The specifications are similar, as well as the service, but thanks to this migration our hosting costs have been cut in half. Keeping in mind that this is paid by a single person, so any little donation helps a lot on this front. ;)
To the surprise of our system administrator, this last migration took only a couple hours with no service interruption reported by our users.
This new forge can be found at forge.dotslashplay.it
. Registrations are open to the public, but we ask you to not abuse this, the main restriction being that we do not wish to host projects unrelated to ./play.it
. Of course exceptions are made for our active contributors, who are allowed to host some personal projects there.
So, if you wish to use this forge to host your own work, you first need to make some significant contributions to ./play.it
The collection of supported games growing endlessly, we have started the development of a public API
allowing access to lots of information related to ./play.it
This API, which is not yet stabilized, is simply an interface to a versioned database containing all the ./play.it
scripts, handled archives, games installable through the project. Relations are, of course, handled between those items, enabling its use for requests like : « What packages are required on my system to install Cæsar Ⅲ
? » or « What are the free (as in beer) games handled via DOSBox
Originally developed as support for the new, in-development, Web site (we'll talk about it later on), this API should facilitate the development of tools around ./play.it
. For example, it'll be useful for whomever would like to build a complete video game handling software (downloading, installation, starting, etc.) using ./play.it
as one of its building bricks.
For those curious about the technical side, it's an API based on Lumen
effectuant that makes requests on a MariaDB
database, all self-hosted on a Debian Sid
. Not only is the code of the API versioned on our forge
, but also the structure and
content of the databases, which will allow those who desired it to install a local version easily.
Based on the aforementioned API, a new website is under development and will replace our current website
based on DokuWiki
Indeed, if the lack of database and the plain text files structure of DokuWiki seemed at first attractive, as ./play.it supported only a handful of games
(link in French), this feature became more inconvenient as the library of ./play.it
supported games grew.
We shall make an in-depth presentation of this website for the 2.13
release of ./play.it
, but a public demo
of the development version from our forge
is already available.
If you feel like providing an helping hand on this task, some priority tasks
have been identified to allow opening a new Web site able to replace the current one. And for those interested in technical details, this web Site was developed in PHP
using the framework Laravel
. The current in-development version is hosted for now on the same Debian Sid
than the API.
A regular comment that is done about the project is that, if the purpose is to make installing games accessible to everyone without technical skills, having to run scripts in the terminal remains somewhat intimidating. Our answer until now has been that while the project itself doesn't aim to providing a graphical interface (KISS principle
"Keep it simple, stupid"), still and always), but that it would be relatively easy to, later on, develop a graphical front-end to it.
Well, it happens that is now reality. Around the time of our latest publication
, one of our contributors, using the API we just talked about, developed a small prototype that is usable enough to warrant a little shout out. :-)
In practice, it is some small Python 3
code (an HCI
completely in POSIX shell is for a later date :-°), using GTK 3
(and still a VTE terminal to display the commands issued, but the user shouldn't have to input anything in it, except perhaps the root
password to install some packages). This allowed to verify that, as we used to say, it would be relatively easy, since a script of less than 500 lines of code (written quickly over a week-end) was enough to do the job !
Of course, this graphical interface project stays independent from the main project, and is maintained in a specific repository
. It seems interesting to us to promote it in order to ease the use of ./play.it
, but this doesn't prevent any other similar projects to be born, for example using a different language or graphical toolkit (we, globally, don't have any particular affinity towards Python or GTK).
The use of this HCI
needs three steps : first, a list of available games is displayed, coming directly from our API. You just need to select in the list (optionally using the search bar) the game you want to install. Then it switches to a second display, which list the required files. If several alternatives are available, the user can select the one he wants to use. All those files must be in the same directory, the address bar on the top enabling to select which one to use (click on the open button on the top opens a filesystem navigation window). Once all those files available (if they can be downloaded, the software will do it automatically), you can move ahead to the third step, which is just watching ./play.it
do its job :-) Once done, a simple click on the button on the bottom will run the game (even if, from this step, the game is fully integrated on your system as usual, you no longer need this tool to run it).
To download potentially missing files, the HCI will use, depending on what's available on the system, either wget
(this last one also handling torrents), of which the output will be displayed in the terminal of the third phase, just before running the scripts. For privilege escalation to install packages, sudo will be used preferentially if available (with the option to use a third-party application for password input, if the corresponding environment variable is set, which is more user-friendly), else su will be used.
Of course, any suggestion for an improvement will be received with pleasure.
Of course, such an announcement would not be complete without a list of the games that got added to our collection since the 2.11
release… So here you go:
- 7 Billion Humans
- Agatha Christie: The ABC Murders
- Age of Mythology Demo
- Among the Sleep
- Anomaly: Warzone Earth
- Another Lost Phone: Lauraʼs Story
- Assault Android Cactus
- Baba Is You
- Blade Runner
- Bleed 2
- Blocks that matter (previously supported by ./play.it 1.x)
- Butcher Demo
- Cineris Somnia
- Commandos 3: Destination Berlin
- Din’s Curse
- Divine Divinity (previously supported by ./play.it 1.x)
- Duet (previously supported by ./play.it 1.x)
- Earthworm Jim
- Edna & Harvey: The Breakout — Anniversary Edition
- Factorio — Demo
- Finding Paradise
- FlatOut 2
- Forgotton Anne
- Freelancer Demo
- Full Throttle Remastered
- Giana Sisters: Twisted Dreams
- Gibbous — A Cthulhu Adventure
- Indiana Jones and the Last Crusade
- Into the Breach
- Kerbal Space Program
- LEGO Batman: The Videogame
- Lego Harry Potter Years 1-4
- Maniac Mansion
- Metal Slug 3 (previously supported by ./play.it 1.x)
- MIND: Path to thalamus
- Minecraftn 4K
- Monkey Island 4: Escape from Monkey Island
- Multiwinia (previously supported by ./play.it 1.x)
- Mushroom 11
- Myst: Masterpiece Edition (previously supported by ./play.it 1.x)
- Neverwinter Nights: Enhanced Edition
- Populous: Promised Lands (previously supported by ./play.it 1.x)
- Populous 2 (previously supported by ./play.it 1.x)
- Prison Architect
- Q.U.B.E. 2
- Quern — Undying Thoughts
- Rayman Origins
- Retro City Rampage (previously supported by ./play.it 1.x)
- Satellite Reign (previously supported by ./play.it 1.x)
- Star Wars: Knights of the Old Republic (previously supported by ./play.it 1.x)
- Starship Titanic
- SteamWorld Quest: Hand of Gilgamech
- Ancient Relics Story Pack
- Arachnoid Portrait Pack
- Distant Stars Story Pack
- Horizon Signal
- Humanoids Species Pack
- Leviathans Story Pack
- Lithoids Species Pack
- Plantoids Species Pack
- Synthetic Dawn Story Pack
- Strike Suit Zero
- Sunless Skies
- Tetrobot and Co.
- The Adventures of Shuggy
- The Aquatic Adventure of the Last Human
- The Count Lucanor
- The First Tree
- The Longing
- The Pillars of the Earth
- The Witcher (previously supported by ./play.it 1.x)
- The Witcher 3: Wild Hunt
- Tonight We Riot
- Touhou Chireiden ~ Subterranean Animism — Demo
- Touhou Hifuu Nightmare Diary ~ Violet Detector
- Triple Triad Gold
- Vambrace: Cold Soul
- VVVVVV (previously supported by ./play.it 1.x)
- War for the Overworld (the base game was already supported, new expansions have been added):
- Heart of Gold
- Seasonal Worker Skins
- The Under Games
- Warcraft: Orcs & Humans
- Warhammer 40,000: Dawn of War — Winter Assault Demo
- Warhammer 40,000: Gladius — Relics of War
- Warlords Battlecry II (previously supported by ./play.it 1.x)
- Wing Commander (previously supported by ./play.it 1.x)
- Wing Commander II (previously supported by ./play.it 1.x)
- Yooka Laylee
- Zak McKracken and the Alien Mindbenders
If your favourite game is not supported by ./play.it
yet, you should ask for it in the dedicated tracker on our forge
. The only requirement to be a valid request is that there exists a version of the game that is not burdened by DRM.
Our team being inexhaustible, work on the future 2.13 version
has already begun…
A few major objectives of this next version are :
- the complete and definitive relegation to the archive bin of ./play.it 1.14, which is still required for about twenty games ;
- the initial release of the new Web site ;
- redaction of documentation towards end-users but also potential contributors ;
- and, after all this time waiting for it, handling of CD‑ROM !
If your desired features aren't on this list, don't hesitate to signal it us, in the comments of this news release. ;)
How do they Differ? Binary Options and CFDs are merely derivatives of traditional forex assets. They are also derivatives of other assets such as commodities, equities and crypto currency. For example, when a trader is buying a CALL option on EURUSD they are in effect entering a long position on the currency pair. The opposite can be said of a PUT option and shorting the asset. The only way ... The bot only works on Windows machines and with the broker binary.com. This is how the Digit Differ Bot Looks. How the Digit Differ Bot looks after reaching the Target Profit. We are trading the Differs Contract with 5 ticks. You win the Digit Differs payout if the last digit of the last tick is not the same as your prediction. The payout does fluctuate depending on the trade amount, but is ... Binary options and digital options differences. You have to make an assumption about the future price direction. However, in binary options trading, this is all that matters, will the price will go up or down from the current market price, while in digital options trading there is an additional factor. Binary options share all of the same underlying factors as traditional vanilla options. When pricing binary options, the same inputs are used to determine its value.The only way in which they differ is their pay-out structure on expiry.. On expiry of a binary option, the pay-out of the option is only one of two outcomes. Binary options trading has long existed over-the-counter, what is the difference between binary and digital options only experiencing a massive growth spurt in the last few years. 1. IQ Option is the only broker in the market to offer this type of options) are somewhat more complicated to understand than other types of options Digital Options offer a high degree of freedom and a higher earning ... What are binary options. A binary option is a type of option with a fixed payout in which you predict the outcome from two possible results. If your prediction is correct, you receive the agreed payout. If not, you lose your initial stake, and nothing more. It's called 'binary' because there can be only two outcomes – win or lose. Advantages of binary options trading. Aside from the ... 1 Tick Digit differ or super digit differ is one one the easiest bot out there. You can check my other bots about ... and make money from binary options and forex. ProvenBinaryBot.com Blog is created to help people to give them some good resources so that they can become successful in the binary options and forex industry. Access All Binary.com Robots. Recent Posts. How To Win Binary Options ...
Enjoy the videos and music you love, upload original content, and share it all with friends, family, and the world on YouTube. binary options trading Digits Over Strategies With Indicators Make $30usd in few minutes - Duration: 16:14. Proudly Tech Money General Tips And Tricks 10,916 views 16:14 Binary Options Guaranteed Latest Digits Differ No Loss Volatility strategies $20usd in 20 MIN - Duration: 19:18. Proudly Tech Money General Tips And Tricks 15,303 views 19:18 Best Binary Options Strategy 2020 - 2 Minute Strategy LIVE TRAINING! - Duration: 43:42. BLW Online Trading Recommended for you. 43:42. B2IQ Copy Trade - O melhor robô agora tem Copy Trade ... Strategi trik binary pasti profit sudah banyak yang berhasil. strategi binary 5 tik, rise fall, digit difers, digit match, touch dan no touch, higher lower sangat mudah dan bisa menghasilkan ... TRIK DIGIT DIFFER BINARY MASIH AMPUH - 2021 Bagi teman teman yang hobi bisnis online trading di platfon Deriv com' binary com, binomo' olymptrade khususnya b... DIGIT DIFFERS BINARY OPTIONS - TIPS & TRICK 95.5 % WIN - Duration: 11:14. Trader Gokil Om Jindul 1,708 views. 11:14. Day Trading Strategies for Beginners: Class 1 of 12 - Duration: 55:18. ... CARA DIGIT DIFFER BINARY TERBARU 2021-PART 19 Bagi teman teman yang hobi bisnis online trading di platfon Deriv com' binary com, binomo' olymptrade khususnya... - Binary.com real account rise fall mt5 digit differ option examples ... Quitting binary option and pausing your trading with the markets basically because of recent failures? Well I was at the ... Make $5 usd Every 2 Minutes Trading Binary Options Digits Differ 100% winning - Duration: 7:11. Proudly Tech Money General Tips And Tricks 11,831 views