Hello to all;
I have been trying nasm assembly on 64 bit windows for a couple months now, and decided to try at making a very simple text based ray-cast maze.
It takes the sin and cosine of a given ray, and uses them as parametric equations, to find the x or y square that is next hit in the casting,
as the data is stored in a character array, consisting of 0, or 10 for walls, and some other number for passageways.
ngl is the current onlooking angle,
snfthrt is 0.5
csfthrt is cosine of 30 degrees,
hlfthrt is 15 degrees,
ln, is the number of columns in the maze array,
fxp, x,
fyp, y,
nthrt2 is 132nd of 30 degrees,
scrn is the output buffer.
The logic all seems to work most of the time, but every so often, spontaneously, some angle will not generate anything, or some way through the 132 angles that make up the projection plane, it will go kapoot.
I really have no idea why this is, maybe someone can find out why?
And maybe someone can find this useful as well?
This function is an almost complete isolate, it just needs a 1d maze array, and an output buffer, and some way to read input.
RyCst:
movsd xmm14, [ngl] ;generate the viewing plane;
addsd xmm14, [hlfthrt]
xor r15, r15 ;column counter for printing;
CstLp:
movsd xmm6, xmm14 ;cast a ray, xmm14 has the input angle;
movsd xmm11, [fxp]
movsd xmm12, [fyp]
mov r12, 512 ;maximum viewing range;
sub rsp, 0x20
movsd xmm0, xmm6
call [cos]
movsd xmm7, xmm0
pxor xmm0, xmm0
movsd xmm1, [nthrt2] ;very small incrment/decrement for round;
mulsd xmm1, xmm1
comisd xmm7, xmm0
jb csng
ja csg
jmp cstsml
csng:
mov rax, -1
cvtsi2sd xmm9, rax
mulsd xmm9, [snfthrt] ;negative round;
jmp getsin
cstsml:
movsd xmm7, xmm1 ;make very small if 0;
csg:
movsd xmm9, [snfthrt] ;otherwise round up;
getsin:
movsd xmm0, xmm6
call [sin]
add rsp, 0x20
movsd xmm8, xmm0
mov rax, -1
cvtsi2sd xmm0, rax
mulsd xmm8, xmm0 ;negate sine as the maze is backwards(in my case);
pxor xmm0, xmm0
movsd xmm1, [nthrt2]
mulsd xmm1, xmm1 ;very small;
comisd xmm8, xmm0
jb snng
ja sng
jmp sntsml
snng:
mov rax, -1
cvtsi2sd xmm10, rax
mulsd xmm10, [snfthrt]
jmp mvry
sntsml:
movsd xmm8, xmm1 ;0.00001;
sng:
movsd xmm10, [snfthrt] ;x11=x,x12=y,x7=cos,x8=sin,x9=xround,x10=yround;
mvry:
movsd xmm5, xmm11
movsd xmm6, xmm12 ;save values;
addsd xmm5, xmm9 ;round x;
cvtsd2si rax, xmm5
cvtsi2sd xmm5, rax ;round;
subsd xmm5, xmm11 ;difference;
divsd xmm5, xmm7 ;x(t);
addsd xmm6, xmm10 ;round y;
cvtsd2si rax, xmm6
cvtsi2sd xmm6, rax
subsd xmm6, xmm12 ;y difference;
divsd xmm6, xmm8 ;y(t);
comisd xmm6, xmm5 ;compare the t's;
ja csht
mov r14, 221 ;flag for y axis hit;
movsd xmm3, xmm6 ;save t(y);
mulsd xmm6, xmm8 ;distance;
addsd xmm12, xmm6
cvtsd2si rax, xmm12
cvtsi2sd xmm12, rax
mulsd xmm3, xmm7
addsd xmm11, xmm3
jmp chkwal
csht:
mov r14, 44 ;flag for x axis hit;
movsd xmm3, xmm5 ;save t(x);
mulsd xmm5, xmm7 ;distance to move;
addsd xmm11, xmm5 ;change x position;
cvtsd2si rax, xmm11
cvtsi2sd xmm11, rax ;make sure on boundary;
mulsd xmm3, xmm8 ;distance for y to move;
addsd xmm12, xmm3 ;change y position;
chkwal:
movsd xmm0, xmm11 ;see if it is a wall;
movsd xmm1, xmm12
cvttsd2si rax, xmm1
cvttsd2si rcx, xmm0
mov rdi, [ln]
mul rdi
add rax, rcx
lea rbx, maze
add rbx, rax
cmp byte [rbx], 0
je htwl
cmp byte [rbx], 10
je htwl
dec r12
cmp r12, 0
jg mvry
htwl:
subsd xmm11, [fxp] ;get the deltas of the coordinates;
subsd xmm12, [fyp]
mulsd xmm11, xmm11
mulsd xmm12, xmm12
addsd xmm12, xmm11
sqrtsd xmm11, xmm12 ;now the length;
movsd xmm15, [csfthrt]
divsd xmm15, xmm11 ;ratio to length at wich view plane is vertically covered(0.866...);
mov rax, 40
cvtsi2sd xmm0, rax
mulsd xmm0, xmm15 ;now in terms of 40;
cvtsd2si rax, xmm0 ;now an integer;
mov rcx, 40
div rcx ;get modulo in rdx, now have number of characters high;
mov rdi, 40
mov rsi, rdx
sub rdi, rdx
shr rdi, 1 ;half;
mov rax, 40
sub rax, rsi
sub rax, rdi ;get the amount to go down after the wall;
lea rbx, scrn
add rbx, r15 ;column number;
prspcs:
mov byte [rbx], ' ' ;print down row the empty spaces halved;
add rbx, 132 ;go down a row;
dec rdi ;count down on the empty spaces;
cmp rdi, 0
jg prspcs
prwlls:
mov byte [rbx], r14b ;print the wall;
add rbx, 132
dec rsi
cmp rsi, 0
jne prwlls ;repeat until the actual height is reached;
ndspcs:
mov byte [rbx], ' '
add rbx, 132
dec rax
cmp rax, 0
jne ndspcs
inc r15 ;next column;
subsd xmm14, [nthrt2]
movsd xmm0, [ngl]
subsd xmm0, [hlfthrt]
comisd xmm14, xmm0 ;see if whole field has been cast over;
ja CstLp ;repeat 0.0039667 radians lower;
sub rsp, 0x28
mov rcx, [stdout]
mov rdx, upstart ;position 0,0 in escape sequence;
mov r8, 7
mov r9, wn
push 0
call [WriteConsoleA]
mov rcx, [stdout]
mov rdx, scrn
mov r8, 5280 ;132x40;
mov r9, wn
call [WriteConsoleA] ;print the view;
add rsp, 0x30
movsd xmm9, [ngl]
movsd xmm0, [nthrt2]
mulsd xmm0, [snfthrt] ;test procedure, to just keep panning until manual stop;
addsd xmm9, xmm0
movsd [ngl], xmm9
jmp RyCst