From 8afdda713d6892d11e61808e291b8037714c3e35 Mon Sep 17 00:00:00 2001 From: Jeremy Penner Date: Sat, 7 Oct 2023 22:49:38 -0400 Subject: [PATCH] rewrite swinemeeper autoreveal in assembly --- asm.jrt | 5 ++- assemble.com | Bin 12957 -> 12988 bytes swine.com | Bin 7705 -> 7731 bytes swine.jrt | 99 ++++++++++++++++++++++++++++++++++++++++++++------- zipoff.com | Bin 20159 -> 20172 bytes zipstub.seg | Bin 4234 -> 4214 bytes 6 files changed, 90 insertions(+), 14 deletions(-) diff --git a/asm.jrt b/asm.jrt index 8173b3d..8790877 100755 --- a/asm.jrt +++ b/asm.jrt @@ -178,7 +178,7 @@ var ignoreimm : >grp3* ( reg -- ) dup 0xf6 ' >extbreg|mem* *? if drop 2ret then 0xf7 ' >extwreg|mem* *? if 2ret then ; - + 1 :op RET- oparg-imm? if 0xc2 >t oparg-val @ w>t then ; 1 :op RETF- oparg-imm? if 0xca >t oparg-val @ w>t then ; 1 :op PUSH @@ -301,6 +301,7 @@ var ignoreimm arg2 oparg-reg? oparg-val @ 0x00 = and arg1 oparg-wreg? and if 0x90 >wreg+op* then 0x86 >bar-war* ; + 2 :op MOV 0x88 >bmr-wmr-brm-wrm* arg2 oparg-imm? arg1 if @@ -325,6 +326,8 @@ var ignoreimm 2 :op RCR 3 >grp2* ; 2 :op SHL 4 >grp2* ; 2 :op SHR 5 >grp2* ; 2 :op SAR 7 >grp2* ; +2 :op TEST 0x84 >bar-war* 0 >grp3* ; + 1 :op NOT 2 >grp3* ; 1 :op NEG 3 >grp3* ; 1 :op MUL 4 >grp3* ; 1 :op IMUL 5 >grp3* ; 1 :op DIV 6 >grp3* ; 1 :op IDIV 7 >grp3* ; diff --git a/assemble.com b/assemble.com index 2fda6b6c761d6fda85991b55ce4f431e432b8e21..f97eb7d5ba3c4c9035110c523e442cddc5d640ca 100755 GIT binary patch delta 423 zcmbQ6x+hiTODs4hNXt$MuLhwvXhJ*45W-_Ym15d7(FsvW@KtSX`{+)R>nP> z53ug!Vf5czB_t}BuuX%7A;dK}gy9!sh4N%WCWf_)B1|m|Z*(RxMyVfT%+h0K@bibr zZZc#9%Q7*5WY!r1WnA6C`p!UQn87k0`pgWzp*~=lXOk}&NSQGhL3FZ$<@4n3U;c1w%=}03(o-w57I4R7$O731BLi>}9CTSTs4$P?GV)mzD1L}l{9b+^E+Un^CcA=ax$N^gIQw lYosUHW!%9eESAmuhGQRdE>n?l1ycmGKF2Y}=*cBUngFvVa;X3S delta 392 zcmdm!IyY72bXYhhNXr-3feayK`!NwI# Q5zP7=#~5uUPd3s7085Q+$p8QV diff --git a/swine.com b/swine.com index bdc7a7fc255ac4221c6450b3213e7ccfdef2f4fb..9ab83837b4bdea946883f59e74a50163ee6a524d 100755 GIT binary patch delta 2722 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 LoN`}`48Z>ZmjL6k diff --git a/swine.jrt b/swine.jrt index e61acdc..d03f613 100755 --- a/swine.jrt +++ b/swine.jrt @@ -92,18 +92,91 @@ array board maxw maxh * allot dup mine? if lose then FREVEALED swap b!| else drop then ; -: visibly-empty? dup revealed? swap squarecount not and ; -: backtrack-square ( p -- p ) boardw @ - 1- dup board < if drop board then ; -: backtrack? ( p -- f ) - dup revealed? over 1+ revealed? and swap 2 + revealed? and not ; -: autoreveal-backtrack ( -- ) - i visibly-empty? i backtrack-square backtrack? and - if i backtrack-square 1- idrop >i then ; -: autoreveal ( -- ) - iterboard each i revealed? not if - i ' visibly-empty? count-neighbours - if i reveal autoreveal-backtrack then - then next ; +var autoreveal-count +( autoreveal: Happens row-at-a-time in optimized machine code. + ar-check-dir: a strip of squares is checked for visibly empty neighbours + against its corresponding square in a given direction, specified with BX. + autoreveal-count is incremented whenever a new square is revealed. + The strips are carefully constructed so as to not step over the edge of + the board. + This is _not_ a Forth word, it's called with CALL by the words below. + autoreveal-row-above: check the nw, n, and ne squares with ar-check-dir. + autoreveal-row-horiz: check the w and e squares with ar-check-dir. + autoreveal-row-below: check the sw, s, and se squares with ar-check-dir. + autoreveal-fast: iterates over the rows of the board and checks each row + against itself and the strips above and below. If anything new is + autorevealed in the current row, we check the previous row again. ) + +L: ar-check-dir + ( in: DI - row to reveal + BX - offset of row to check + CH - 0, CL - count of squares to check + out: DI, BX, CX - preserved + trampled: AX, DX ) + MOV AX DS + MOV ES AX + MOV AL FREVEALED # ( AL - byte value of visibly empty square ) + ( DI is now row to check, BX+DI is row to reveal ) + MOV DH CL + ADD DI BX + NEG BX + DEC BX ( DI will be one past the square that was checked when SCASB returns ) +0 :> + JCXZ 2 @> ( end of row, exit ) + REPNZ SCASB ( search for visibly empty square ) + JNZ 1 @> ( none found, exit ) + MOV DL @[ BX+DI] + TEST DL AL + JNZ 0 <@ ( already revealed, keep searching ) + OR DL AL + AND DL FFLAG ~ # + MOV @[ BX+DI] DL + INC @[ autoreveal-count @] + JMP 0 <@ +1 <: 2 <: + ( revert DI, BX and CX to previous value ) + MOV CL DH + SUB DI CX + INC BX + ADD DI BX + NEG BX + RET + +:asm autoreveal-row-above ( p -- ) + POP DI + MOV CX @[ boardw @] + MOV BX CX NEG BX ( directly above ) + CALL ar-check-dir +L: autoreveal-left-right + DEC CX INC BX ( to the right ) + CALL ar-check-dir + DEC BX DEC BX INC DI ( to the left ) + CALL ar-check-dir + NEXT + +:asm autoreveal-row-horiz ( p -- ) + POP DI + MOV CX @[ boardw @] + XOR BX BX ( on the current square ) + JMP autoreveal-left-right + +:asm autoreveal-row-below ( p -- ) + POP DI + MOV CX @[ boardw @] + MOV BX CX ( directly below ) + CALL ar-check-dir + JMP autoreveal-left-right + +: autoreveal-fast + iterrows each + 0 autoreveal-count ! + i autoreveal-row-horiz + i board > if i autoreveal-row-above then + i lastrow? not if i autoreveal-row-below then + i board > autoreveal-count @ and if + ( backtrack ) i + then + next ; : won? ( -- f ) 1 iterboard each i b@ FMINE FREVEALED | & not if not break then next ; @@ -114,7 +187,7 @@ array board maxw maxh * allot if click neighbours each i reveal next else drop then ; : reveal-at square-at dup revealed? if reveal-unflagged-neighbours? else reveal click then - autoreveal check-win ; + autoreveal-fast check-win ; : flag-noise ( p -- ) b@ FFLAG & if moop else meep then ; : flag-at square-at dup revealed? not if FFLAG swap dup flag-noise b!^ else drop then ; diff --git a/zipoff.com b/zipoff.com index 3ed5dadb759b3ab999ef6cb308d9b069e1449559..8411ac16e9a66908c4d192c30de270bd2b70684a 100755 GIT binary patch delta 7155 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 delta 7147 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 diff --git a/zipstub.seg b/zipstub.seg index b2c09dc62483e7a2c2e086b593ce5c1b70120874..b9e386f5e658621529f015d93d4b0ad01fe9020b 100755 GIT binary patch delta 84 zcmeBD{HCxWo0BzOOoK6ga{=cZRz}m!y!^6^f-<}dcx(jEGsZG934UWd%BVBhUqD=? n04Oq@k%6(3$(N~wQ-b9iqc78JPDiE;&ZCSag5gZZ84DNzs7@6+ delta 122 zcmeyS(51K`o0By_OoK6Ca{=cZRz|DMy!^6^2_6Cqcq{~8b1V`#%BUlFTA+Y2iBX1k z0Z)M7dB#{qCc$rvM;RRik24-;1j*QPnlhbdlxDii?8~%?u?47RIwJ#PCzCHz38w_h WH%4Ek*_@6{8JtHMI|Rd-Kzac1hadO=