I have no further documentation on that; it is just an idea that I have carried around in the back of my head for a long time, but ever got to actually working on it. But I can elaborate a bit on it here. It always bothered me that testing King-move legality does duplicate work. E.g. with a King on g2 and an enemy Rook on h8 you would test for emptiness of h7, h6, h5, h4 for each of the moves Kh1, Kh2 and Kh3. So it seems more efficient to do a one-time effort to determine which squares are attacked by Rh8, and then for each move just test the King to-square based on that information.
Contact attacks are quite easy to handle. You could assign a bit to each of the 8 King steps (e.g. 1 = forward, 2 = backward, 4 = left, 8 = right, 16 = left-forward, ...), and tabulate as a function of the relative position of the King (a 16x15 table 'contact_hits' if you use 16x12 board) which of these steps move into the check for the various piece types, packing that into an integer. E.g. the lowest 8 bits for orthogonal steps (R+Q+K), the next 8 bits for forward-diagonal (B+Q+K+wP), the next 8 for backward diagonal (B+Q+K+bP) and the higest 8 bits for Knight jumps. You would have a table indexed by piece type with masks that would clear the bits not relevant for that piece (e.g. 0xFF000000 for a Knight, 0x00FFFF00 for a Bishop), so that
hit = contact_hits[location[king] - location[piece]] & contact_code[piece];
would give you the set of directly attacked squares (actually four sets differentiated by attack type,packed in one int). For generating King move you would then loop through the 8 directions, and test
if( (hit & to_bit[direction])) == 0) GenerateOneMove(location[king], location[king] + king_step[direction]);
where to_bit would be an 8-entry table that contains 0x01010101, 0x02020202, 0x04040404, ... to test if the to-square is safe from attacks by all existing move types.
But sliders complicate this plan, as they require testing for a free path. Q can actually make distant attacks on the King neighborhood along 3 different rays. E.g. Ke4, Qd3 would attack d5 (dependent on occupation of d4) and f3 (dependent on e3). The attack on f5 in that case should really behandled as a contact attack, because although it will always be blocked by the King, the latter cannot hide behind itself. But unfortunately there are no bits left in the contact_hits table for indicating jumps of two. It depends a bit on whether you also want the scheme to work for positions where you already are in check. Of course you also could accept a small inefficiency here, treating the distant attack that X-rays the King (and thus checks it) as any other distant attack, but remove the King from the board before the whole procedure, so that it seems unblocked when you make the (redundant) test.
On second thought, it could be reasonably efficient to do something like you do now after the King moves for testing slider attacks, but then before the King move. So basically generate slider moves, but in stead of testing whether they hit the King, you record where they intersect the King neighborhood. And you generate only moves in directions that could possibly intersect the King neighborhood. I normally base my move generation on a zero-terminated list of board steps, where the piece type determines which list will be used (and where for sliders each board step will then be applied repeatedly until you hit an obstacle). Instead of having this depend only on piece type, you could make separate lists for each (piece_type, location), i.e. a board-size table. I actually do that in my Xiangqi engine; it has the advantage that in edge squares you can omit directions that immediately stray over the edge, so that no time is wasted on them. (And in Xiangqi there are zone edges inside the board as well that certain piece types cannot cross, so you automatically take care of piece confinement that way,e.g.of the King to the Palace.) You could do something similar here, where each piece type has a 16x15 table indexed by the relative position to King that contains the (zero-terminated) list of possible board steps that set you on a course that intersects the King neighborhood.
You could then have a 16x15 table neighborhood, which would tabulate which square in the King neighborhood corresponds to the relative position with which it is indexed. E.g. if you used '1' to indicate the square in front of the King in the 'hit' code, and a forward step adds 16 to the square number (as it would in a 16x12 board), you would initialize neighborhood = 1. During the ray scans of the listed directions you would then calculate
hit |= neighborhood[to - location[king]];
so that all bits in 'hit' corresponding to squares attacked by sliders will also be set. You would have to remove the King while doing this, to prevent it from trying to hide in its own shadow. A problem is that the ray scans will overshoot the King neighborhood, which wastes time. You would want them to stop when you leave the King neighborhood again (if they ever get that far). For this you could make a second table that for each board step that can reach the King neighborhood would contain the last square of this intersection that you will reach (relative to King) if unobstructed, and terminate the ray scan when you reach it.
Most of the sliders would be positioned such that their moves would not even intersect the King neighborhood on an otherwise empty board, so that the zero-terminated list of board steps will be empty, and the amount of work will be limited to looking up their contact attacks as described above, and the first board step (concluding that it is zero). This work will then be shared by all King moves.