Author Topic: Simple Text Ray-Caster  (Read 9799 times)

Offline ALGOL9000

  • Jr. Member
  • *
  • Posts: 4
Simple Text Ray-Caster
« on: May 30, 2021, 09:00:29 PM »
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

Offline ALGOL9000

  • Jr. Member
  • *
  • Posts: 4
Re: Simple Text Ray-Caster
« Reply #1 on: May 31, 2021, 05:20:30 PM »
I have solved the problem, I was thinking about something else when I did the modulo at the bottom, I wound up leaving rax alone, and just flipped some other registers for the height to be simpler, then I was using jne when jg was what I should have used for filling the array.
This tiny mishap caused me much woe.

Offline ALGOL9000

  • Jr. Member
  • *
  • Posts: 4
Re: Simple Text Ray-Caster
« Reply #2 on: June 03, 2021, 01:17:17 AM »
It also needed to have a tiny increment in the forward direction for every individual ray, although this results in there being a small glitch as every so often the wrong axis is crossed before the wall is hit.