#include "game_types.h"

/* Coroutine threader (4-arg): spills (a, b, c, d) to the frame, threads the
   head struct a[] = {b, BE0 -> B68, c, d}, and chains GetStackFrame ->
   FreeObject3(a) -> Pop/Push -> FreeObject3(a) -> Pop/Push, returning a.
   Yields suspend at every resume PC; the C below is one logical pass. */
/* Collision_SweepTest @ 0x08017008 (real 320B) -- sweep test threading (a, c, d), returns a. Mirrors src/matched/Collision_SweepTest.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;

int *Collision_SweepTest(int *a, int b, int c, int d)
{
    int *fr = Mem_GetStackFrame();
    Frame blk;
    a[1] = 0x02000BE0;
    a[0] = b;
    /* block 0, resumes at 0x08017054 */
    blk.link = fr[1];
    blk.zero = 0;
    blk.self = (int *)&blk;
    blk.resume = 0x08017054;
    blk.sp = (int *)&blk;
    fr[1] = (int)&blk;
    a[1] = 0x02000B98;
    fr[1] = *(int *)fr[1];
    /* block 1, resumes at 0x0801708C */
    blk.link = fr[1];
    blk.zero = 0;
    blk.self = (int *)&blk;
    blk.resume = 0x0801708C;
    blk.sp = (int *)&blk;
    fr[1] = (int)&blk + 24;
    Mem_FreeObject3((int)a, 0);
    fr[1] = *(int *)fr[1];
    Mem_PopStack();
    Mem_PushStack();
    /* block 2, resumes at 0x080170D0 */
    blk.link = fr[1];
    blk.zero = 0;
    blk.self = (int *)&blk;
    blk.resume = 0x080170D0;
    blk.sp = (int *)&blk;
    fr[1] = (int)&blk + 48;
    a[1] = 0x02000B68;
    a[2] = c;
    a[3] = d;
    fr[1] = *(int *)fr[1];
    /* block 3, resumes at 0x0801711C */
    blk.link = fr[1];
    blk.zero = 0;
    blk.self = (int *)&blk;
    blk.resume = 0x0801711C;
    blk.sp = (int *)&blk;
    fr[1] = (int)&blk + 72;
    Mem_FreeObject3((int)a, 0);
    fr[1] = *(int *)fr[1];
    Mem_PopStack();
    Mem_PushStack();
    return a;
}
