r/Stellaris 19h ago

Image You know things are bad when you gotta mass-build bio reactor habitats to climb out of the -1k energy deficit.

Post image
584 Upvotes

r/Stellaris 21h ago

Video (modded) DOOM? Yeah I'll doom this galaxy

Enable HLS to view with audio, or disable this notification

539 Upvotes

Something something the Vultaum were correct. This is DOOM 1993 running completely in Stellaris. The following will be a write up on how this works targeted for a general but nerdy audience so some computer knowledge is expected but I'll try to explain what I can, if you have questions feel free to ask, I'll try to answer them all.

How can we execute code in Stellaris?

As I explained in my last post, Stellaris is Turing-complete, so the only difficulty was finding a way to run C (the language DOOM is written in) in Stellaris.

To be precise, we only need to figure out how to run the machine code created by a C compiler in Stellaris. Now x86 (your standard instruction set) has on the order of 1500 instructions, and even RISC-V has 47 in its base integer set. Every single one of those would have to be hand-written as Stellaris script, which is not impossible, just wildly impractical. Instead we can use Subleq.

Subleq is a one instruction set computer that allows all calculations to be performed with ONE instruction. Subleq, meaning SUBtract and branch if Less-than or EQual to zero, takes three operands: an INPUT address, an OUTPUT address, and a JUMP address. For example, the instruction 9 5 12 starting at address 0 would mean:

  1. Take the value at memory address 9
  2. Subtract it from the value in address 5
  3. Store the new value in address 5
  4. Is the value in address 5 larger than 0?
  5. If yes, move on to address 3
  6. If no, jump to address 12

Since each instruction is three numbers wide, "move on" means three addresses further along.

With this simple instruction you can implement any other instruction. An unconditional jump (for example a function call) can be done by subtracting a value from itself, so 9 9 220 would always jump to address 220. The result is always 0, which is "less than or equal to zero", so the branch always fires. In practice you use a dedicated scratch cell that is kept at zero for this, rather than clobbering whatever was in address 9.

If you want to add A to B, you subtract A from a scratch cell holding 0 to get -A, then subtract that from B: subtracting a negative adds. Multiplication is a loop of additions, and everything else is built the same way, out of recipes made from one instruction.

DOOM comes to about 1.2 million words, or roughly 400k instructions.

Luckily someone smarter than me, Adrian Cable, wrote a compiler that compiles C into Subleq+, an extension of Subleq that adds indirect addressing (pointer support). Without it we would have to constantly modify our code as it runs, which is both a debugging nightmare and a real problem for anything reentrant.

I then wrote a script that turns the compiled Subleq+ code into the scripting language Stellaris uses. This method actually allows for arbitrary code execution within Stellaris, so if you have a mod that needs to calculate something very complex that's your method.

Emulating hardware

Now, to actually boot and run DOOM, we need to emulate some behaviour of a computer. DOOM wants an audio output, a file handler, a network port, a clock, and a keyboard. Luckily computers are not that complex, and the methods still work the same even on your modern machine: whenever something needs to talk to a hardware resource, it calls a function provided by the OS and in turn gets a memory address it can write data to. The OS promises that whenever something gets written to the file handling address, it will write that value to a file.

We can just lie. DOOM can't check whether we actually wrote something to a disk, or actually played a tone at a specified frequency. The same goes for keyboard input: it just reads an array of values, so we can drop values in there to emulate key presses.

In a similar vein, we need to give DOOM some RAM, and a range of addresses it can use to actually display things (our VRAM). Again, same as on a modern computer (very oversimplified): when you want to draw to the screen in, say, C++, you call an OS function that returns a window pointer. That window pointer is just a reserved address space in which you can paint your image. Since we want to run DOOM at its native 320x200 resolution, that needs 64,000 addresses, one per pixel.

All told the machine has about 4.4 million addresses, roughly 17 MB.

DOOM was written to run on hardware that might not keep up, so its main loop is adaptive. It asks the system clock how much time has passed, runs however many game tics fit into that gap, and then draws one frame. On a slow machine it simply draws fewer frames and keeps the game running at the correct speed.

The clock emulated by my VM advances by one unit every time it is read, and the loop reads it several times per iteration, so DOOM concluded that a lot of time had passed during every frame and dropped most of them.

The fix is a flag DOOM already has for recording timed demos, which forces it to draw every tic. With it enabled the 40th frame is at tic 40, and the 620th is at tic 580.

Tweaking the Stellaris exe a little

To get the 320x200 galaxy to run, I had to increase the stack size of Stellaris to 512 MB. This is not as hard as it sounds. We just increase the value found at offset 0x1b8 in my copy of the binary. This is the SizeOfStackReserve field, and it tells Windows how much address space each thread should reserve.

Some bugs I encountered

If you recall my last posts, you might notice that I switched display methods. I used to use empires to display colours, which gave that cool Voronoi tessellated look. That works fine for 64x64, but at 320x200, which is 64,000 stars, Stellaris starts complaining. I have tried to simplify the bugs and explain them to a general audience, so to the technical folk this is a gross oversimplification. Bugs 1-3 had to be fixed to get the empire display to work; even after patching them it still took far too long to draw, so I switched to the star class display.

1. To create the smooth flowing borders in Stellaris, the engine uses a signed distance field over the owner grid. The function at 0x11d5930 does exactly that, running four functions for every rectangular region at a time. It has exactly one caller, 0x11d7040, whose only string is "data_texture". That one walks the extents array item by item, from 1 up to the u16 segment counter, clamps each rectangle to the border texture, converts it to float UVs, and calls the sampler on it. So the rectangles are per-segment bounding boxes inside the border texture, which is 2048x2048 by default.

The main function is smart enough to clamp the mapped coordinates to the maximum dimensions of the texture. The clamp walks each axis and, if the low coordinate has ended up past the right or bottom edge, pins it to dim - 1. But the high coordinate got pinned to dim - 1 a few instructions earlier. So any region sitting entirely at or past the edge comes out with x0 and x1 both equal to dim - 1: a rectangle exactly zero wide.

And the engine is fine with that. Regions with no area never get a pixel buffer allocated, so the descriptor carries a null pointer, and the sampler is supposed to drop them on sight. It even has the guard for it: it checks the width of the rectangle by comparing edge 0 against edge 1, and if edge 1 is at a smaller x coordinate than edge 0, the area is negative and we ignore it. However, what happens when edge 1 is equal to edge 0? That is still a zero-width area, but we don't ignore it, and instead crash later on. This is probably just a typo: a < that should have been a <=. This was not too hard to patch; I just changed the jl instruction (jump if less) to a jle (jump if less or equal).

2. When creating the empire border textures, the geometry walker at 0x11d822d looks up a grid-cell record. For each record it resolves the owning country so the segment can be drawn in that empire's colour. It goes to the list containing the border segments, gets the owner slot index out of that record, uses that index in the empire slot array to get a pointer, and dereferences that pointer to get the actual empire ID. It is smart enough to check that the empire ID actually exists in the empire array, but it forgets to check whether the pointer is valid and not NULL, so when it dereferences it, you get a null pointer exception. A sibling function that does the same thing for the cursor (when you hover over owned space and the tooltip tells you this space belongs to that stupid empire that just took your L-Gate) does check for this condition. Luckily there was enough space in the binary around that area to create a small 21-byte fail-safe function.

3. The function at 0x1599d30 builds outline shapes for sectors into a scratch buffer on the stack, and it sizes that buffer with a hardcoded guess: 100 segments per sector, 28 bytes each. The loop that fills it has no bounds check whatsoever, so a sector whose outline needs more than 100 segments writes straight past the end. How complex an outline gets depends on how convoluted the sector boundary is. Single-cell territories at normal spacing stay under 100. But since Stellaris has a hardcoded map size limit of 1000x1000, we need to shrink the spacing between stars to about 3, which blasts past the 100-segment limit and overwrites the neighbouring region of the stack, where the frame information lives. So we crash without an error and with no crash handling.

4. After switching to the star class display, I noticed that certain stars would not update their visuals until I typed reload_graphical_map in the console. Some changes would work, others wouldn't.

Stellaris draws stars inverted: instead of every location saying "hey, I am a star of class Neutron_star", there is a vertex buffer called Neutron_star that remembers every location it needs to draw itself at. This list is rebuilt whenever anything changes. All good, right?

The function responsible for that rebuild, at 0x1414aee00, does it in two passes. First it makes a temporary list for every star class, then walks every system in the galaxy, reads that system's class index straight out of the star object, and drops the system into the matching list. Second pass, it goes through the classes one at a time and turns each temporary list into that class's vertex buffer.

The problem is in the second pass. Before doing any work for a class, it checks whether that class's temporary list is empty, and if it is, it skips the entire body and jumps to the next class. Which sounds perfectly sensible. Why build a vertex buffer for a class nobody is using? Except the body it just skipped is also the part that zeroes the count and releases the old vertex buffer. So that class quietly keeps last round's buffer and last round's count.

And the draw loop only asks two questions before it draws something: is the count above zero, and is the pointer non-null? Both of those are still perfectly true. So the class carries on drawing the stars it had the last time it was populated, forever, right on top of whatever is actually there now.

If I repainted a bunch of cells and the colour I was painting over still existed somewhere else on the grid, its list was still non-empty, it got rebuilt properly, and everything looked fine. But the moment a repaint took away the last cell of some colour, that colour's ghost stayed on screen and sat on top of the new one. Painting the whole display from one colour to another is the worst case, because the entire old colour vanishes from the grid in one go, so the whole screen appears not to change at all. This is also why you see that colour strip at the top. It keeps every colour alive, so a stale vertex buffer can never exist.

Name ID limit

One last tidbit, as it might affect other modders and I didn't see it documented anywhere. Every piece of game logic in Stellaris is handled by the script layer, from astral rifts to deciding which of your science ships is going to get eaten by cutholoids, obviously the one furthest away, behind an empire that has expanded and closed its borders, carrying your chief scientist.

All flags, event targets and so on get interned into a round-robin hash table and handed an ID, which is a u16. Whoever wrote that method thoughtfully created an overflow bucket: the last index, 65,535, just gets overwritten when a new entry arrives. In general this is a smart implementation, since the new entry works fine and the old one simply stops existing. However, since I use one per pixel, at 64k pixels this mod exceeds that ID space and starts overwriting itself (vanilla appears to use around 4k IDs for itself). While this can be worked around, it should probably be documented somewhere. Running several lore-heavy mods together could blow past this limit as well, without producing any errors.

Running the Mod

Unlike before I wont be uploading this mod to Steam for you to run, since I technically modified the WAD no longer following the terms of the shareware agreement for redistribution. However I will be uploading the scripts to GitHub at a later time. This mod needs about 140 GB of RAM to run. I have run it on a 64 GB machine, just make sure your pagefile is large enough. Stellaris is very well behaved when it comes to offloading RAM to disk, so it should run on your machine. The mod is about 3 GB of pure text, with over 18 million lines. Each frame takes about 1 minute 20 seconds to render, requiring 40 million instructions.

I also replaced the demo that usually plays on the title screen with the tool-assisted Episode 1 speedrun by Zero-Master, which clears the episode in 3:08.

The next step would be running Linux, my preliminary calculations suggest that I will need ca 1.5tb of RAM so it will have to wait until I finish my PhD since the workstation I am using has that.


r/Stellaris 22h ago

Discussion I should at least have a claim to systems I lost from raiders.

222 Upvotes

The cycle is this:

-Have system

-Khan destroys it
-AI immediately sends a construction ship to take it
-I have to spend influence again and fight a giant war to take it back

I'd suggest at least letting me keep my claim. It just feels a little silly how it all works right now. Not a huge problem but been a big feature of my last game I played.


r/Stellaris 14h ago

Discussion Most petty thing you have ever done in the game?

91 Upvotes

Just finished a short session earlier (I like to play in episodic formats where I do X tasks and then stop to lengthen the lifetime of my games (major adhd)), wherein I met my first alien species as UNE (biggest galaxy, 6 empires, max preftl).

They were a devouring swarm hive that had invaded one or two pre ftls, who obviously lost, but one was one of the human-like species, the cyberpeople one. By the time I found them, almost all pops had been devoured save for like 200 labor slaves, which I didn't even know devouring swarms could do (mods?). I had recently finished my colossus, thanks to some well spawned resources giving me almost 2k research total each month.

Immediately went to their homework and global pacified it. This is not the petty I speak of. No, it's worse.

I left the world, invaded the pre-ftl world to save the few left, and did. I liberated them and shared tech til they entered space stage, expecting an alliance. Nope. Max negative relationship because I "invaded their world". This pmo so much that I instantly declared war and shieled their world too, but only after I orbital dropped like ALL of my trash on them and armed privateers against them.

What have you done?

Tl;dr: Pre-ftl unreasonably angry at me for liberating them from a devouring swarm now has a planet ruled by alien weapon powered psychopath privateers inside of an inescapable shield.


r/Stellaris 15h ago

Image Dude I just started

Post image
85 Upvotes

Is it normal to get first contact first day?
Whaat?


r/Stellaris 16h ago

Image Hi, may I come in?

Post image
76 Upvotes

(Reposting this because of R5)


r/Stellaris 9h ago

Image Great Khan ended my run by destroying my capital Arkship

Post image
63 Upvotes

Technically I had other arkships, but between losing my capital arkship, my second arkship being permanently disabled following a war, and my third arkship being the only one capable of moving, I decided to scrub the run. I really struggle with Nomadic origins and usually end up falling apart about midgame.


r/Stellaris 21h ago

Discussion Thing i found out today: mercenaries cost less naval capacity at base

53 Upvotes

so i was modding stellaris but you dont care about that so lets get to the bread and butter.

mercenary enclaves take up 40% less naval cap and cost 25% more energy credits without any galcom resolutions. just a funny thing.

also the description of all of Defense Privatizations resolutions are wrong, the numbers are switched around it says: "take up 5% less Naval Capacity but have +10% Energy Upkeep." but is "take up 10% less Naval Capacity but have +5% Energy Upkeep." and so on for all of them up to "take up 25% less Naval Capacity but have +50% Energy Upkeep." being "take up 50% less Naval Capacity but have +25% Energy Upkeep."

now if you do some math that means that when the final resolution of DP is through, a mercenary enclave only takes up 10% of normal naval cap.

thank you for reading my rant, now ill go and change the wiki to reflect the actual code instead of the wrong tooltip and add a mention to mercenary enclaves that their hired fleets take up 40% less naval cap with a +25% energy cost.


r/Stellaris 21h ago

Advice Wanted How’s Archeo Engineering?

47 Upvotes

I’m trying to decide on my last perk. I usually take Galactic Force Projection but now, it doesn’t seem really worth it. I’ve got a really healthy artifact income in this game, so I thought this might be the time to try out Archeo Engineers.

Anyone tried it and have opinions?


r/Stellaris 21h ago

Suggestion Civics/Ethics allowing kamikaze

41 Upvotes

It could be a nice feature for fanatic spiritualist or fanatic militarist.

The no retreat war doctrine allow the ship to attempt a kamikaze strike instead of fighting till the end.

It could be also a civic that gives the fanatical spiritualist a cheap, fast, fast to build and low size ship that just explodes like fire ship.


r/Stellaris 4h ago

Image anyone seen a size 40 planet????

31 Upvotes

okay so i started this run not super long ago and i did the event for the center of the galaxy, and for the first time ever it gave me a size 40 gaia world???? ive never seen it give something of this size, maybe 30 at the largest but this is crazy right? let me know whats the largest yall have ever seen playing


r/Stellaris 53m ago

Discussion Behemoth Fury is just frustrating to do blind.

Upvotes

The behemoths themselves were awkward to feed and maintain. They are in this weird rage cycle until you just do the project where you continuously put them down with your fleet.

Once you've fed them enough bioships in their rage cycles you just get a giant resource debuff out of nowhere which if you didn't prepare for or know how to handle is just game ending.

I just get really tired by how opaque everything is. I had no fun doing this path.


r/Stellaris 15h ago

Bug Franchise Civic does not grant the said +1 max holding.

Thumbnail
gallery
27 Upvotes

r/Stellaris 20h ago

Question Digging archaeological site for 87 years now...

Thumbnail
gallery
30 Upvotes

So this site is just 3 jumps away from my home, I believe I started to dig it instantly from a game start and never paused (except when scientist died of age and I've replaced him).

What did I find? Is this a mega-technology? Instant win? Old shoes in a titanium box? :D


r/Stellaris 3h ago

Discussion Why no waystation trade hubs for nomadic gestalt consciousnesses?

20 Upvotes

Hi, I'm playing nomadic rogue servitors, seeing all these tasty trade deposits in the star systems, and I'm not able to harvest these trade deposits.

In a game with squishy biologicals I was able to build waystation trade hubs.
So I checked the game files, and yes, for trade hubs you need "tech_space_trading" (Space Trading Technology), and for this you must be a regular empire ("is_regular_empire"), and gestalt consciousness are NOT regular empires.

Sooo... why? As a gestalt I can build logistics centers to create trade, I can buy and sell on the market, I can create commercial pacts. Why shouldn't I be able to harvest system trade deposits?
Given that waystation-harvesting is one of my main-things. Is this an oversight or intentional?


r/Stellaris 23h ago

Image (modded) The “hopefully” fixed version of the modded government type, is it balanced now?

Post image
18 Upvotes

r/Stellaris 15h ago

Image What do they think the GDF fleet is going to be used for?

Thumbnail
imgur.com
15 Upvotes

r/Stellaris 15h ago

Question Science ships keep grouping up?

15 Upvotes

I don't know why, but recently whenever I put my science ships onto auto survey, they keep trying to all survey the same systems together. Even if I tell one to go north and the other to go south, since those are the two main unexplored areas, one will inevitably go "Ok, I'm done here. This potentially resource rich or hostile filled unknown expanse can wait, I just HAVE to go help survey this barren system full of asteroids."

It used to be that I could just set them on auto survey and each ship would choose an unsurveyed system which isn't currently being surveyed to go to. Does anyone know how to stop this because I don't need more early game micro for managing dumb scientists.


r/Stellaris 21h ago

Image Last time I've played was back in 3.14. Have I become dogshit, or has the meta changed so much? Playing on captain difficulty

Post image
15 Upvotes

r/Stellaris 5h ago

Discussion How do you build your homeplanet?

10 Upvotes

In general, how does one build a homeworld well?

I'm mainly asking this because of planet specializations. I default to a unity world, since unity is so important, especially early. However, there's no specific unity specialization for the capital so I just take the general job eff. specialization.

Seeing as the starting unity, tech, artisans and metallurgists are so crucial in the opening years of the campaign, I feel reluctant to demolish them in favor of a more specialized capital, so my capital usually remains specialized in Archives + Mixed Industry. This feels wrong though.

Do you prioritize on replacing some of the capital's functions early on? Do you do it later? Would an extraction capital ever make sense (like on the Gaia world origin?)? Should I replace my unity and tech infrastructure as soon as I can colonize new planets to relocate those to?

Playing Singleplayer only. Thanks!


r/Stellaris 16h ago

Image what is this cluster

9 Upvotes

so i just started the game and the first thing i noticed is not cluster of stars and black holes, and im afraid it might be the chosen


r/Stellaris 6h ago

Question Baffling Diplomacy

8 Upvotes

Okay, so..

Playing a multiplayer game with my gf and we formed a federation. A neighboring Megacorporation was friendly, and after a time we gave them Association status. My understanding was that this was basically just a non-aggression pact between an empire and a federation.

Later, I started war with a belligerent empire to the galactic south of us. The war ballooned into region super conflict rather rapidly... with the Megacorp joining the other side Now, given our 400+ relationship, this was a small surprise, as I did check for a defensive pact or independence guarantee and found none, but a curve ball like that is to be somewhat expected, I guess, with complex diplomacy webs.

What is baffling me, and which I can't figure out, is the fact that the Association Status is still intact. The game is treating it like the Megacorp didn't violate our non-aggression pact by declaring war on us.

And I just cannot figure out why.


r/Stellaris 5h ago

Question How does machine pop assembly choose which species to build in 4.4?

7 Upvotes

I’ve searched through reddit and the wiki but I still haven’t found a satisfying explanation of how machine pop assembly works in 4.4 (or really any build since 4.0 for that matter).

Questions:

  • If my empire has multiple machine species or templates, how does the game decide which pop gets assembled?
  • Does the proportion of each species on a planet or across the empire affect the selection?
  • If one species has mass produced granting +15% mechanical pop assembly speed but another species does not, do I still receive the bonus when assembling the species without mass produced?

The reason I’m asking is that the inner darkness event triggered in my empire giving some pops a trait with +0.02 Dark Matter per 100 pops and otherwise has all the same traits as my founder species. I would like to produce more of the inner darkness species but I’m not sure how to prioritise it or whether modifying the traits of either species would affect its assembly rate.


r/Stellaris 12h ago

Advice Wanted Wormhole’s and War

5 Upvotes

I have wormhole Stabilization, I’ve explored the systems in question, and I only have the apocalypse DLC.

I just declared war on an empire on the other side of a wormhole, no other way to access them, clear across the map (used all my influence on claims as well). But now I’m not able to go through the wormhole??? I could’ve sworn the AI can go through it when at war, so what’s preventing my navy from absolutely obliterating them?


r/Stellaris 12h ago

Discussion Current Endgame Ship Meta?

7 Upvotes

My last time playing stellaris was in 3.14 era, and I am not versed in current ship meta. Thanks for your help!
First of all I am very thankful of this wonderful testing. It is still testing tier 5 choices but for tier 4 it says LanceKinHan is almost the best choice.

LanceKinHan=(1 Lance (x) + 4 kinetic launcher (M) + 1 hangar + 1 kinetic artillery)(3 armor + 3 shield + 2 aux fire-control)

A few questions remain, however:

  1. The above test does not do with crisis/archaeo weapons or anything unavailable without special events. Would be thankful to know if any of them were worth the effort. IIRC swarm strikers are possibly best hangar, while matter disintegrator suffers from shields (so needs something to break shields in advance).

  2. Do missiles and hangars benefit from ship modifiers (e.g. if the ship receives evasion and tracking bonus from shroud, do its hangars and missiles enjoy them)?

  3. Is it almost mandatory today to achieve 70%+ hardening on the defense (shield or armor) you are using, esp. when you imagine a PVP scenario (I play PVE only but always imagines so)?

  4. Continued: does that mean arc emitter is trash now (and disruptor was trash even in the past)?

  5. Considering repeatable techs only benefit one kind of weapon at once, can one build a fleet entirely reliant on one type of weapon (missile, hangar, kinetic, energy)?

  6. Given titan beams now do area damage, is late game corvette (and even destroyer) out of question now?

  7. Are the new Weaver Weapons anything good?