#include "game_types.h"

/* Coroutine-dispatch family (HandleType0-15 + Spatial_GetNeighbor): all 17
   share one shape and differ only in pools. Each function runs the stack
   frame through 5 setup blocks bracketed by resume PCs (b enter; pool;
   b skip), chaining: GetStackFrame -> GetStackFrame_08015DC8 ->
   Collision_Resolve -> Mem_Swap (+Pop/PushStack) -> Mem_FreeObject3
   (+Pop/PushStack). The null-guard exits early when *guard != 0... in
   practice the guard slot always holds a list head here, so the body runs.
   Stack switching (mov sp / mov pc tails) is the coroutine yield; the C
   below describes one logical pass. */
/* Collision_HandleType11 @ 0x08018F20 (real 320B) -- collision type 11 via the coroutine
   dispatcher (guard 0x020014dc). Mirrors src/matched/Collision_HandleType11.c. */
extern int *Mem_GetStackFrame(void);
extern int *Mem_GetStackFrame_08015DC8(void);
extern int Collision_Resolve(int *a, int b);
extern void Mem_Swap(int *a, int *b);
extern void Mem_PopStack(void);
extern void Mem_PushStack(void);
extern void Mem_FreeObject3(int a, int b);

typedef struct {
    int link;
    int zero;
    int *self;
    int resume;
    int *sp;
} Frame;

void Collision_HandleType11(void)
{
    int *guard = (int *)0x020014dc;
    int *fr = Mem_GetStackFrame();
    Frame blk;
    if (*guard != 0)
        return;
    /* block 1: link frame, resume 0x08018F5C */
    blk.link = fr[1];
    blk.zero = 0;
    blk.self = (int *)&blk;
    blk.resume = 0x08018F5C;
    blk.sp = (int *)&blk;
    fr[1] = (int)&blk;
    fr[1] = *(int *)fr[1];
    /* block 2 (via GetStackFrame_08015DC8): resolve, resume 0x08018F8C */
    Mem_GetStackFrame_08015DC8();
    blk.link = fr[1];
    blk.zero = 0;
    blk.self = (int *)&blk;
    blk.resume = 0x08018F8C;
    blk.sp = (int *)&blk;
    {
        int slot[6];
        slot[0] = (int)&blk + 24;
        Collision_Resolve(slot, 0);
    }
    /* block 3: swap, resume 0x08018FB8; data word 0x08CA02F8 */
    blk.link = fr[1];
    blk.zero = 0;
    blk.self = (int *)&blk;
    blk.resume = 0x08018FB8;
    blk.sp = (int *)&blk;
    (void)0x08CA02F8;
    {
        int slot[6];
        slot[0] = (int)&blk + 48;
        Mem_Swap((int *)0x02000BE0, slot);
    }
    fr[1] = *(int *)fr[1];
    Mem_PopStack();
    Mem_PushStack();
    /* block 4: free path, resume 0x08019008 */
    blk.link = fr[1];
    blk.zero = 0;
    blk.self = (int *)&blk;
    blk.resume = 0x08019008;
    blk.sp = (int *)&blk;
    *(int *)0x02000C30 = 0; /* resume-PC store slot */
    /* block 5: free object, resume 0x08019038 */
    blk.link = fr[1];
    blk.zero = 0;
    blk.self = (int *)&blk;
    blk.resume = 0x08019038;
    blk.sp = (int *)&blk;
    {
        int slot[6];
        slot[0] = (int)&blk + 24;
        Mem_FreeObject3(slot[0], 0);
    }
    fr[1] = *(int *)fr[1];
    Mem_PopStack();
    Mem_PushStack();
}
