The easy way is to read the CGA status register in a tight loop. Or rather several tight loops: one to find the vsync pulse, then one to find the start of the active area, then as many as you need to find the scanline that you want. Once you've synchronised the CPU with the CRTC you can reprogram CRTC registers on particular scanlines to set up the sequence of CRTC frames that you want. For example, you might set up a 127 scanline frame, then a 135 scanline frame. You'll need to program the vertical sync position register differently in the different CRTC frames as well as vertical total adjust and vertical displayed. You might also want to change the start address registers if you don't want to display the same thing in both frames. https://github.com/reenigne/reenigne/blob/mas … 00line/l100.asm is the source for the portraits effect in 8088 MPH so you can study that as an example and play around with it.
That way involves the CPU spending a lot of time reading the CGA status register, so the more advanced way is to set up the PIT to fire IRQ0 at appropriate times in the frame. By programming new periods into port 0x40 (without resetting the PIT by writing to port 0x43) you can have IRQ0s occurring at irregular intervals (e.g. scanline 0 and 100). We used that trick in some places in 8088 MPH and Area 5150. It leaves more CPU time free for other things, but is more complicated to set up, and one must be aware that interrupts being disabled for too long might lead to the effect breaking.