Skip to content

Rectangle Overlap

Reuse the Amiga’s unsigned word-edge box test, with touching-edge errors, wider-coordinate limits and native proof.

Code status: assembled and emulator-executed. A500 OCS PAL, Kickstart 1.3, Asm198x 0.0.72, Build198x 0.2.9 and Emu198x 0.44.2 are the recorded configuration.

Two boxes share area and demo displays 1. In custom, B moves until it touches A’s right edge; the result is 0. The helper is the maintained Collect and Respond collision routine, unchanged. Build with make, boot build/demo.adf on an A500 OCS PAL with Kickstart 1.3, and reset to leave. Asm198x 0.0.72 and Build198x 0.2.9 build this original OFS caller.

Include and call

Include ../../framework/collect-and-respond/collision.inc once, outside fall-through execution, in writable memory. Write four unsigned word edges into each of rect_a and rect_b: left, top, right, bottom. Call bsr boxes_overlap. D0 is 1 for overlap and 0 for apart/empty; CCR changes. Other registers survive. There is no initialisation, allocation or I/O. The routine owns 16 bytes of rectangle state and uses the caller’s normal return stack. Serialise access with interrupts if they share these records.

Assembly
    move.w #2,rect_a
    move.w #2,rect_a+2
    move.w #8,rect_a+4
    move.w #6,rect_a+6
    ; Fill rect_b too.
    bsr boxes_overlap
    tst.w d0
    beq no_hit

Right and bottom are excluded: [2,2,8,6] spans six by four units. Touching edges/corners do not share area. Empty or reversed extents return false. All edges must fit 0–65535; these are unsigned word comparisons, not signed screen coordinates. A left edge of 65535 cannot make a positive-width box inside this domain. Form right/bottom from position and size in wider arithmetic and validate/clip before narrowing. Do not let 65530+16 wrap. A separately qualified signed/long variant would be needed for negative world coordinates.

The helper costs 88 instruction bytes and 16 state bytes. Its early exits make runtime depend on the geometry; no cycle budget is measured here. The original diagnostic executable is 13,824 bytes, including the 10,240-byte one-plane display, case table, results, copper list and caller. Those are not helper costs. Copper/bitplane setup belongs to the standalone caller, which takes over custom chips/interrupts and does not return to AmigaDOS. The pure test can instead run inside an OS-friendly engine with its own display.

Customise and diagnose

Change the eight example edges in custom.asm. Smaller collision bounds can forgive a close miss, while larger interaction bounds make items easier to collect. Collision need not match artwork. Keep the response—damage, collection or room entry—outside the helper. A box test can be a cheap broad phase before mask/pixel tests on the remaining candidates, each with its own code, data and CPU costs.

wrong-touch.inc deliberately accepts equality in the four separation checks. With touching geometry, wrong incorrectly displays 1. The empty/reversed checks remain intact. Restore the original comparisons; repaired has exactly the custom executable and returns 0. The fault adds eight instruction bytes. Keep it separate from normal builds.

Independent qualification

Every native caller traverses 184 supplied edge cases at the word range, including swapping arguments, empty/reversed rectangles, containment, touching/corner cases, separation and 65535 limits. A max/min interval oracle is independent of the machine’s separating-axis instruction sequence. Positive completion markers, a unique relocated program signature and real result bytes must agree. The guest owns its case traversal; the observer neither writes results nor moves the PC.

Verification retains the original executable, parsed single-hunk relocation data, native instruction/case-data readback, tool/firmware identities, all results, full bitplane and PNG. Each changed relocation is applied to the original code before native comparison. The glyph in the plane and visible capture must both agree with the result. Fault and repair are independently cold-booted. Corrupt code, observations, source pins, include tables and pixel expectations fail the publication gate.

Run python3 scripts/check-amiga-rectangle-overlap.py and python3 -m unittest discover -s scripts -p test_amiga_rectangle_overlap.py -v from the samples root. Re-capture with verify-amiga-rectangle-overlap.py and explicit assembler/build198x/emulator/Kickstart paths. Emu198x 0.44.2 A500 OCS PAL/Kickstart 1.3 is the selected configuration, not every Amiga or original-hardware timing. No firmware is distributed.

Maintained implementation and caller

collision.inc
; Half-open unsigned word edges [left,top,right,bottom].
; Reject empty/reversed boxes and touching edges. Returns D0=1/0; CCR changes.
; Other registers survive. Caller forms edges without word overflow.
boxes_overlap:
    move.w rect_a,d0
    cmp.w rect_a+4,d0
    bhs boxes_apart
    move.w rect_a+2,d0
    cmp.w rect_a+6,d0
    bhs boxes_apart
    move.w rect_b,d0
    cmp.w rect_b+4,d0
    bhs boxes_apart
    move.w rect_b+2,d0
    cmp.w rect_b+6,d0
    bhs boxes_apart
    move.w rect_a,d0
    cmp.w rect_b+4,d0
    bhs boxes_apart
    move.w rect_b,d0
    cmp.w rect_a+4,d0
    bhs boxes_apart
    move.w rect_a+2,d0
    cmp.w rect_b+6,d0
    bhs boxes_apart
    move.w rect_b+2,d0
    cmp.w rect_a+6,d0
    bhs boxes_apart
    moveq #1,d0
    rts
boxes_apart:
    moveq #0,d0
    rts
rect_a: dc.w 0,0,0,0
rect_b: dc.w 10,5,11,6
demo.asm
    section code,code_c
    include "cases.inc"
    include "caller.inc"
helper_start:
    include "../../framework/collect-and-respond/collision.inc"
helper_end:
example: dc.w 2,2,8,6,6,4,11,7
    include "case-table.inc"
program_end:
caller.inc
start:
    lea $dff000,a5
    move.w #$7fff,$09a(a5)
    move.w #$7fff,$09c(a5)
    move.w #$7fff,$096(a5)
    lea case_table,a2
    lea results,a3
    move.w #CASE_COUNT-1,d7
case_loop:
    lea rect_a,a0
    moveq #7,d6
copy_case:
    move.w (a2)+,(a0)+
    dbra d6,copy_case
    bsr boxes_overlap
    move.b d0,(a3)+
    dbra d7,case_loop
    move.w #$cafe,completed
    lea example,a0
    lea rect_a,a1
    moveq #7,d6
copy_example:
    move.w (a0)+,(a1)+
    dbra d6,copy_example
    bsr boxes_overlap
    move.w d0,result
; Set up the maintained one-plane PAL display, independent of the helper.
    lea plane,a0
    move.l a0,d0
    lea copbpl,a1
    move.w d0,6(a1)
    swap d0
    move.w d0,2(a1)
    lea copperlist,a0
    move.l a0,$080(a5)
    move.w #0,$088(a5)
    lea zero,a0
    tst.w result
    beq show_digit
    lea one,a0
show_digit:
    lea plane+1984,a1
    moveq #7,d2
copy_glyph:
    move.b (a0)+,(a1)
    adda.w #40,a1
    dbra d2,copy_glyph
    move.w #$8380,$096(a5)
    move.w #$babe,ready
hold:
    bra hold
caller_code_end:
signature: dc.b "198XRECTAMIGA!",0
    even
completed: dc.w 0
ready: dc.w 0
result: dc.w 0
results: dcb.b CASE_COUNT,0
    even
zero: dc.b 60,66,70,74,82,98,60,0
one: dc.b 24,56,24,24,24,24,126,0
    even
copperlist:
    dc.w $08e,$2c81,$090,$2cc1,$092,$0038,$094,$00d0
    dc.w $100,$1200,$102,0,$104,0,$108,0,$10a,0
    dc.w $180,$012,$182,$fff
copbpl:
    dc.w $0e0,0,$0e2,0
    dc.w $ffff,$fffe
plane: dcb.b 10240,0
custom.asm
    section code,code_c
    include "cases.inc"
    include "caller.inc"
helper_start:
    include "../../framework/collect-and-respond/collision.inc"
helper_end:
example: dc.w 2,2,8,6,8,2,13,6
    include "case-table.inc"
program_end:
wrong-touch.inc
; Deliberate fault: accept boundary equality.
; Half-open unsigned word edges [left,top,right,bottom].
; Reject empty/reversed boxes and touching edges. Returns D0=1/0; CCR changes.
; Other registers survive. Caller forms edges without word overflow.
boxes_overlap:
    move.w rect_a,d0
    cmp.w rect_a+4,d0
    bhs boxes_apart
    move.w rect_a+2,d0
    cmp.w rect_a+6,d0
    bhs boxes_apart
    move.w rect_b,d0
    cmp.w rect_b+4,d0
    bhs boxes_apart
    move.w rect_b+2,d0
    cmp.w rect_b+6,d0
    bhs boxes_apart
    move.w rect_a,d0
    cmp.w rect_b+4,d0
    beq wrong_accept_5
    bhs boxes_apart
wrong_accept_5:
    move.w rect_b,d0
    cmp.w rect_a+4,d0
    beq wrong_accept_6
    bhs boxes_apart
wrong_accept_6:
    move.w rect_a+2,d0
    cmp.w rect_b+6,d0
    beq wrong_accept_7
    bhs boxes_apart
wrong_accept_7:
    move.w rect_b+2,d0
    cmp.w rect_a+6,d0
    beq wrong_accept_8
    bhs boxes_apart
wrong_accept_8:
    moveq #1,d0
    rts
boxes_apart:
    moveq #0,d0
    rts
rect_a: dc.w 0,0,0,0
rect_b: dc.w 10,5,11,6
The working overlap caller displays 1.
A shared area returns 1. This native one-plane display is caller instrumentation, not a helper requirement.
The faulty edge-contact caller incorrectly displays 1.
The equality error reports overlap for touching boxes. The repaired caller has identical geometry and returns 0.

Pinned reusable code and caller · Native configuration and proof. Maths for Games connects intervals, numeric width and coordinate conversion; AABB geometry describes the same test independently of a machine.