#name ^.Object.BCheck
#type &ffd

#include <Bolmaster$Path>Sources.Structures
#include <Bolmaster$Path>Sources.Variables
#set hitbit=1<<7
#set baseshift=3; 8 pixel block size
#set netshift=2 ; 4x4 net blocks per graphics block
;on entry
;R10=object pointer

STMFD R13!,{R10,R14}
LDR R3,[R10,#8]
LDR R4,[R10,#12];get R3=x, R4=y

LDR R5,[R10,#16]
LDR R6,[R10,#20]
ADD R3,R3,R5    ;add suggested velocity to object
ADD R4,R4,R6

LDR R5,[R10,#28];size entry
MOV R6,R5,LSL #16
MOV R6,R6,LSR #16
MOV R5,R5,LSR #16
MOV R5,R5,LSL #12     ;R5=xsize, R6=ysize
MOV R6,R6,LSL #12     ;in pixels <<12

SUB R3,R3,R5,LSR #1
SUB R4,R4,R6,LSR #1  ;R3 and R4 point to the top left of the object

CMP R3,#0            ;check if the object strays off the levelnet
BLT fail             ;on it's bottom or right sides
CMP R4,#0
BLT fail
LDR R7,[R12,#v.netxsize]
LDR R8,[R12,#v.netysize]
MOV R7,R7,LSL #netshift
MOV R8,R8,LSL #netshift
ADD R0,R3,R5
CMP R0,R7,LSL #12+baseshift
BGE fail
ADD R1,R4,R6
CMP R1,R8,LSL #12+baseshift
BGE fail


MOV R0,#0
MOV R1,#0
BL checkperim
BEQ pass

LDR R3,[R10,#8]  ;get original position
LDR R4,[R10,#12]
SUB R3,R3,R5,LSR #1 ;of top left corner
SUB R4,R4,R6,LSR #1
LDR R7,[R10,#16] ;get velocity
LDR R8,[R10,#20]
AND R1,R3,#&FFF
AND R2,R4,#&FFF
SUB R3,R3,R1
SUB R4,R4,R2
ADD R7,R7,R1
ADD R8,R8,R2

MOVS R9,R7
RSBMI R9,R9,#0
MOVS R11,R8
RSBMI R11,R11,#0

.check1
CMP R9,#0
CMPLE R11,#0
BLE done
MOV R0,R7
MOV R1,R8
BL checkperim
BNE check2
.checkins
ADD R3,R3,R0
ADD R4,R4,R1
SUB R7,R7,R0
SUB R8,R8,R1
SUBS R9,R9,#1<<12
SUBS R11,R11,#1<<12
B check1

.check2
MOV R0,R7
MOV R1,#0
BL checkperim
BNE check3
B checkins

.check3
MOV R0,#0
MOV R1,R8
BL checkperim
BNE check4
B checkins

.check4
B done



.pass
ADD R0,R10,#8
LDMIA R0,{R3-R6}
MOV R0,PC
ORR R0,R0,#1<<30; set zero flag
TEQP PC,R0
LDMFD R13!,{R10,PC}

.done
ADD R3,R3,R5,LSR #1  ;get back to normal R3,R4
ADD R4,R4,R6,LSR #1
LDR R1,[R10,#8]
LDR R2,[R10,#12]

SUB R5,R3,R1
SUB R6,R4,R2
MOV R0,PC
BIC R0,R0,#1<<30; clear zero flag
TEQP PC,R0
LDMFD R13!,{R10,PC}


.fail
MOV R0,PC
BIC R0,R0,#1<<30; clear zero flag
TEQP PC,R0
LDMFD R13!,{R10,PC}





;checkperim checks the perimeter of the object for collisions
;on entry to checkperim R3=x, R4=y, R5=xsize, R6=ysize

.checkperim
CMP R0,#1<<12
MOVGT R0,#1<<12
CMP R0,#-1<<12
MOVLT R0,#-1<<12
CMP R1,#1<<12
MOVGT R1,#1<<12
CMP R1,#-1<<12
MOVLT R1,#-1<<12
STMFD R13!,{R0-R11,R14}
SUB R5,R5,#1
SUB R6,R6,#1
ADD R3,R3,R0
ADD R4,R4,R1
LDR R11,[R12,#v.levelnet]   ;these are globals required for the fast
LDR R10,[R12,#v.levelshift] ;translate routine
ADD R10,R10,#netshift
translate R7,R3,R4  ;x,y
ADD R0,R3,R5
translate R8,R0,R4  ;x+dx,y
MOV R9,#1
  .loop0
  LDRB R0,[R7],R9
  TST R0,#hitbit
  BNE checkperimfail
  CMP R7,R8
  BLE loop0

translate R7,R3,R4 ;x,y
ADD R1,R4,R6
translate R8,R3,R1 ;x,y+dy
LDR R9,[R12,#v.netxsize]
ADD R7,R7,R9,LSL #netshift  ;skip what we've already checked
CMP R7,R8
BGT cpskip1
  .loop1
  LDRB R0,[R7],R9,LSL #netshift
  TST R0,#hitbit
  BNE checkperimfail
  CMP R7,R8
  BLE loop1
.cpskip1

ADD R0,R3,R5
translate R7,R0,R4 ;x+dx,y
ADD R0,R3,R5
ADD R1,R4,R6
translate R8,R0,R1 ;x+dy,y+dy
LDR R9,[R12,#v.netxsize]
ADD R7,R7,R9,LSL #netshift
CMP R7,R8
BGT cpskip2
  .loop2
  LDRB R0,[R7],R9,LSL #netshift
  TST R0,#hitbit
  BNE checkperimfail
  CMP R7,R8
  BLE loop2
.cpskip2

ADD R1,R4,R6
translate R7,R3,R1 ;x,y+dy
ADD R0,R3,R5
ADD R1,R4,R6
translate R8,R0,R1 ;x+dy,y+dy
MOV R9,#1
ADD R7,R7,R9
SUB R8,R8,R9
CMP R7,R8
BGT cpskip3
  .loop3
  LDRB R0,[R7],R9
  TST R0,#hitbit
  BNE checkperimfail
  CMP R7,R8
  BLE loop3
.cpskip3
CMP R0,R0
LDMFD R13!,{R0-R11,PC}
.checkperimfail
; returns NE as already set
LDMFD R13!,{R0-R11,PC}

macro translate m0,m1,m2
{
  MOV m0,m2,LSR #12+baseshift
  ADD m0,R11,m0,LSL R10
  ADD m0,m0,m1,LSR #12+baseshift
}

