What WAS the cause anyway?
I wish i knew exactly.
GDI Heap Extender works this way: [**** i suck at diagrams]
There are GDI handles pointing to 16-bit local heap memory blocks.
Handles are stored in handle tables and consist of 4 bytes: pointer to block (2 bytes) and flags (2 bytes).
When GDI Heap Extender kicks in, handles are decoupled from blocks. It preallocates several memory blocks [arenas] in 16-bit heap (~1% of resources) and provides those blocks for active GDI handles with special LRU algorithm:
* when new handle is allocated, it points to least used arena. if handle was using this arena, it is 'swapped out': contents are moved into special 'shadow' 32-bit heap. handle is marked by special 'mutated' flag 0x80. this value is not defined nor used in 16-bit heap.
* when GDI function receives handle marked as 'mutated', it must 'unmutate' it the same way: find least used arena, 'swap out' its contents, and 'swap in' object contents.
That's pretty much is it. This way each bitmap handle costs only 4 bytes to GDI heap, not 44 as before, thus potentially there is 10 times possible improvement. There are other limitations for bitmaps (global memory, LDT, 32-bit GDI heap) but best case it's really 10+ times.
GDI Heap Extender also can increase performance sometimes, and that's not obvious. I'll tell ya later.
So what was the problem? 0x80
. It seems in Chozo4 case some program/driver is abusing handles the way i do, so I added simple check if it's really a bitmap.