I've had a bunch of ideas for ways to dynamically generate new pattern data, but they're only really useful when you're limited on the amount of ROM you can access. (In practice, that can only be because larger memories are too expensive).
You connect the output of the ROM to a barrel shifter, allowing tiles to shift left-right within the tile.
... or any other function mapping some data from the ROM to the result, such as left-right reflection.
You can change how the row-of-tile lines from the PPU connect to the ROM, allowing up-down reflection or shifting things up and down within the tile.
You can change how the bitplane selector is mapped, allowing palette swaps within a tile (simplest is swapping colors #1 and #2)
You might find the KimKlone an interesting read.With 16 bits instead of 8, we can encode all sorts of crazy stuff to happen when a byte is read.
Vertical offset-per-tile (SNES) / "each 2cell vscroll" (Genesis) would fit fine in something like MMC5. It's basically identical to MMC5's left-and-right split screen, but 33 times instead of just twice.Column offsets. This would look really cool, but would also involve recreating most of PPU's addressing logic on the cartridge. Note that simple column offsets would fit fine in attribute space, if you're not using it, because of EXRAM or something. Also note that with addressing logic recreated, a split assist function would be easy to implement, fixing the two prefetched tiles and reducing h-blank write needs to horizontal scroll.