(subsequent edit: I understand the games quoted in the OP had more limited movement options meaning this probably isn't the method used, but I'll leave it here as an example of games like Doom and Wolfstein. Also see @2br-2b's answer with video which explains it well)
Starting at left of observer's field of view, cast a 'ray' out in 2D. This is a position in the 3D space in front of observer, let's imagine at waist height, starting at the observer's position and moving forward until it hits something eg the side of a wall. Imagine firing a ray horizontally at your left-most peripheral vision.
At the point where it hits a wall: we know the position on the wall that it strikes, meaning we know which part of our wall image should be shown.
The 2D-> 3D bit:
Get a vertical sliver of the wall image from top to bottom and plonk that on the screen view, scaled to the distance from the observer. Ie from a 2D position we get all of the wall top to bottom for that spot, but just that one vertical sliver.
Now do the same for the the next position (ie not quite leftmost field of view).
Each time you get a whole vertical slice of the image of the wall, so there's no idea of "up and down". The limitations are something like..
- The height of the wall is usually constant unless some extra programming is added to take that into account (actually this would be pretty easy but might slow things down with extra calculation)
- The corners in walls are always vertical on the screen, not angled/tilted.
- So the player can't 'look up' - ie the horizontal angle of their view can't be anything other than .. um .. horizontal, although it'd be possible to 'jump' the wall corners are still vertical on screen.
- The walls are usually in a maze made of right-angled wall corners, because a diagonal wall would show up in 'steps'. This might not matter if the ray angle increments is small enough though.
To explain further: my HTML/JS version of this placed a DIV at the point where the ray strikes a wall.
The screen x-position of the DIV is the ray angle I'm running at the moment (which angle out of the 120 degrees).
The screen Y position is always cented vertically.
The height is determined by how far away that wall strike was (=original height / distance away * a zoom factor).
The DIV is as wide as I've divided the ray angle increment up by and the height is determined by how far away the strike is.
The image to fill the Div is grabbed from a static wall image, the x position being how far along the wall the strike occurred, and scaled to fit the DIV.
I hope I've explained it well enough to understand!
I expect there are other methods and this might not be a definitive "this is how they all worked" but it's one way of doing it.