Programming thread

  • 🐕 I am attempting to get the site runnning as fast as possible. If you are experiencing slow page load times, please report it.
If you want a true challenge beyond C, x86 or ARM Assembly. I find the lower level languages to be way more interesting than the higher level ones personally speaking. Initially when I was looking into programming for video game hobbyist shit, I was looking at C++ and potentially Rust because of the Bevy Engine. I would eventually take a side quest and started looking into operating systems their order of operations, and eventually x86 Assembly.
I wrote a minesweeper knock-off in x86 assembly, but any attempts I've made to modify it lately have just resulted in it hanging, and I'm not sure whether to blame DosBox or my coding skills for that...

Code:
a
call    040B            ;_seed
mov     ax,000d
int     10              ;Set video mode 0d (320x200x16 graphics)
;Set mouse horizontal min/max position
mov     ax,7
mov     cx,0000
mov     dx,027f         ;max horizontal position (0-639 for some reason?)
int     33
inc     ax
mov     dx,00c7         ;max vertical position
int     33
;Set mouse graphics cursor
inc     ax
xor     bx,bx
xor     cx,cx
mov     dx,0568         ;_cursor_masks
int     33
;Display the initial grid
xor     cx,cx           ;CH=text column 0-39, CL=text row 0-24
;_draw_cell
mov     dl,19           ;25 rows
sub     dl,[077C]       ;_grid_size+1 (height)
shr     dl,1            ;divide by 2
mov     dh,28           ;40 columns
sub     dh,[077B]       ;_grid_size+0 (width)
shr     dh,1            ;divide by 2
add     dx,cx
mov     si,05A8         ;_sprite_s
call    0535            ;_draw_sprite
inc     ch
cmp     ch,[077B]       ;_grid_size+0 (width)
jnz     0125            ;_draw_cell
xor     ch,ch
inc     cl
cmp     cl,[077C]       ;_grid_size+1 (height)
jnz     0125            ;_draw_cell
mov     ax,1
int     33              ;Show mouse cursor
;Check for keypress/mouse click
;_input_loop
mov     ax,3
int     33
and     bx,3
jnz     0175            ;_handle_click
mov     ah,06
mov     dl,ff
int     21
jz      0154            ;_input_loop
cmp     al,1b
jnz     0154            ;_input_loop
;_quit_to_dos
mov     ax,0002
int     10              ;Set video mode 2 (25x80x16 text)
mov     ax,4c01
int     21              ;return to DOS
;_handle_click
cmp     bl,4
jz      01E8            ;_wait_for_mouseup
;shr    cx,4            ;divide by 16
db      c1,e9,04
;shr    dx,3            ;divide by 8
db      c1,ea,03
mov     ch,cl           ;CH=column
mov     cl,dl           ;CL=row
mov     dl,19           ;25 rows
sub     dl,[077C]       ;_grid_size+1 (height)
shr     dl,1            ;divide by 2
mov     dh,28           ;40 columns
sub     dh,[077B]       ;_grid_size+0 (width)
shr     dh,1            ;divide by 2
cmp     ch,dh
jb      01E8            ;_wait_for_mouseup
cmp     cl,dl
jb      01E8            ;_wait_for_mouseup
sub     cx,dx           ;CX=click location (CH=column, CL=row)
mov     dx,[077B]       ;_grid_size+0 (DH=height, DL=width)
cmp     ch,dl
jnb     01E8            ;_wait_for_mouseup
cmp     cl,dh
jnb     01E8            ;_wait_for_mouseup
test    bl,2
jz      01F5            ;_left_click
;jnz    01B3            ;_right_click
;_right_click
mov     si,0800         ;_grid_revealed
call    0445            ;_get_cell_data
test    al,1
jnz     01E8            ;_wait_for_mouseup
mov     si,07C0         ;_grid_flags
call    0472            ;_set_cell_data
mov     si,06E8         ;_sprite_f
test    al,1
jnz     01C9            ;+2
mov     si,05A8         ;_sprite_s
mov     dl,19           ;25 rows
sub     dl,[077C]       ;_grid_size+1 (height)
shr     dl,1            ;divide by 2
mov     dh,28           ;40 columns
sub     dh,[077B]       ;_grid_size+0 (width)
shr     dh,1            ;divide by 2
add     dx,cx
mov     ax,2
int     33              ;Hide mouse cursor
call    0535            ;_draw_sprite
mov     ax,1
int     33              ;Show mouse cursor
;_wait_for_mouseup
mov     ax,3
int     33
cmp     bx,0
jnz     01EB            ;-2
jmp     0154            ;_input_loop
;_left_click
mov     si,0800         ;_grid_revealed
call    0445            ;_get_cell_data
test    al,1
jnz     01E8            ;_wait_for_mouseup
mov     si,07C0         ;_grid_flags
call    0445            ;_get_cell_data
test    al,1
jnz     01E8            ;_wait_for_mouseup
cmp     word ptr [077E],-1      ;_cells_remaining
jnz     0267            ;_check_click
;_init_grid
mov     di,cx           ;DI=click location (column, row)
mov     al,[077B]       ;_grid_size+0 (width)
mul     byte ptr [077C] ;_grid_size+1 (height)
mov     [077E],ax       ;_cells_remaining
mov     bp,ax           ;BP=height*width
;_get_random_loc
mov     cx,bp
call    03BC            ;_rnd_scaled
div     byte ptr [077B] ;_grid_size+0 (width) (AH=column, AL=row)
mov     bx,ax           ;BX=mine location (BH=column, BL=row)
mov     cx,di           ;CX=click location (CH=column, CL=row)
sub     bh,ch
jnb     0231            ;+2
neg     bh              ;BH=absolute value of BH-CH
sub     bl,cl
jnb     0237            ;+2
neg     bl              ;BL=absolute value of BL-CL
cmp     bh,bl
jb      023D            ;+2
xchg    bh,bl           ;place the larger value in BL
cmp     bl,1            ;check to see if mine is within 1 cell of click
jbe     021E            ;_get_random_loc
mov     cx,ax           ;CX=mine location (CH=column, CL=row)
mov     si,0780         ;_grid_mines
call    0445            ;_get_cell_data
test    al,1
jnz     021E            ;_get_random_loc
mov     si,0780         ;_grid_mines
call    0472            ;_set_cell_data
dec     word ptr [077E] ;_cells_remaining
xor     ah,ah
mov     al,[077D]       ;_grid_size+2 (number of mines)
add     ax,[077E]       ;_cells_remaining
cmp     ax,bp
ja      021E            ;_get_random_loc
mov     cx,di           ;CX=click location (CH=column, CL=row)
;jmp    023f            ;_check_click
;_check_click
mov     si,0780         ;_grid_mines
call    0445            ;_get_cell_data
test    al,1            ;Check for mine at click location
jz      0298            ;_count_mines
;_lose
mov     ax,2
int     33              ;Hide mouse cursor
;Flag the bomb that exploded so the draw routine won't redraw the sprite
mov     si,07C0         ;_grid_flags
call    0472            ;_set_cell_data
mov     dl,19           ;25 rows
sub     dl,[077C]       ;_grid_size+1 (height)
shr     dl,1            ;divide by 2
mov     dh,28           ;40 columns
sub     dh,[077B]       ;_grid_size+0 (width)
shr     dh,1            ;divide by 2
mov     bp,dx           ;BP=top left offset
add     dx,cx
mov     si,0708         ;_sprite_x
call    0535            ;_draw_sprite
jmp     02CA            ;_game_over
;_count_mines
call    04A7            ;_reveal_cell
dec     word ptr [077E] ;_cells_remaining
jz      02A7            ;_win
dec     bp
jl      031F            ;_open_board
jmp     01E8            ;_wait_for_mouseup
;_win
mov     ax,2
int     33              ;Hide mouse cursor
mov     dl,19           ;25 rows
sub     dl,[077C]       ;_grid_size+1 (height)
shr     dl,1            ;divide by 2
mov     dh,28           ;40 columns
sub     dh,[077B]       ;_grid_size+0 (width)
shr     dh,1            ;divide by 2
mov     bp,dx           ;BP=top left offset
;Patch the game over loop to update the memory addresses that need to be
;changed so it flags bombs & prints the win message instead of game over
mov     word ptr [2F3], 06E8    ;_sprite_f
mov     word ptr [30A], 0772    ;_win_message
;_game_over
;Loop through the whole grid and display the remaining unflagged bombs
xor     cx,cx
;_game_over_loop
mov     si,07C0         ;_grid_flags
call    0445            ;_get_cell_data
shl     al,1
mov     dx,ax
mov     si,0780         ;_grid_mines
call    0445            ;_get_cell_data
or      al,dl
cmp     al,2
jnz     02EE            ;+6
mov     si,0748         ;_sprite_e
mov     dx,bp
add     dx,cx
call    0535            ;_draw_sprite
jmp     02F7            ;+5
cmp     al,1
jnz     02F7            ;+3
mov     si,0728         ;_sprite_b
jmp     02E5            ;-7
inc     ch
cmp     ch,[077B]       ;_grid_size+0 (width)
jb      02CC            ;_game_over_loop
xor     ch,ch
inc     cl
cmp     cl,[077C]       ;_grid_size+1 (height)
jb      02CC            ;_game_over_loop
mov     dx,0768         ;_lose_message
mov     ah,09
int     21              ;display string
mov     ah,06
mov     dl,ff
int     21
jz      0314            ;-1
cmp     al,1b
jnz     0314            ;-3
jmp     016B            ;_quit_to_dos
;_open_board
xor     cx,cx           ;CX=cell location 0,0
;_open_board_loop
mov     si,07C0         ;_grid_flags
call    0445            ;_get_cell_data
shl     al,1
mov     dx,ax
mov     si,0800         ;_grid_revealed
call    0445            ;_get_cell_data
or      al,dl
cmp     al,3
jz      0356            ;_open_cells
inc     ch
cmp     ch,[077B]       ;_grid_size+0 (width)
jb      0321            ;_open_board_loop
xor     ch,ch
inc     cl
cmp     cl,[077C]       ;_grid_size+1 (height)
jb      0321            ;_open_board_loop
;No more cells need to be opened
cmp     word ptr [077E],0       ;_cells_remaining
jnz     0353            ;+2
jmp     02A7            ;_win
jmp     01E8            ;_wait_for_mouseup
;Open the cells surrounding this one and then toggle the placeholder flag off
;_open_cells
mov     dx,cx           ;DX=middle cell location
cmp     cl,0
jz      035F            ;_open_cells_row_increment
dec     cl
;_open_cells_row_increment
cmp     ch,0
jz      0366            ;_open_cells_loop
dec     ch
;_open_cells_loop
cmp     cx,dx           ;skip the middle cell
jz      037F            ;_open_cells_increment
mov     si,0800         ;_grid_revealed
call    0445            ;_get_cell_data
test    al,1
jnz     037F            ;_open_cells_increment
push    cx
push    dx
call    04A7            ;_reveal_cell
pop     dx
pop     cx
dec     word ptr [077E] ;_cells_remaining
;_open_cells_increment
mov     bx,dx           ;BX=lower right corner of area to open
inc     bh
cmp     bh,[077B]       ;_grid_size+0 (width)
jnz     038B            ;+2
dec     bh
inc     bl
cmp     bl,[077C]       ;_grid_size+1 (height)
jnz     0395            ;+2
dec     bl
cmp     ch,bh
jz      039D            ;+3
inc     ch
jmp     0366            ;_open_cells_loop
mov     ch,dh
cmp     cl,bl
jz      03A7            ;+3
inc     cl
jmp     035F            ;_open_cells_row_increment
mov     cx,dx
mov     si,07C0         ;_grid_flags
call    0445            ;_get_cell_data
cmp     al,0
jz      03B9            ;+3
mov     si,07C0         ;_grid_flags
call    0472            ;_set_cell_data
jmp     031F            ;_open_board
;Get a random number less than CX. Result is stored in AX.
;_rnd_scaled
mov     dx,0001
cmp     cx,0
jl      03CD            ;+5
shl     cx,1
shl     dx,1
cmp     cx,0
jge     03C4            ;-3
call    03DB            ;_rand
cmp     ax,cx
jnb     03CD            ;-2
mov     bx,dx
xor     dx,dx
div     bx
ret
;Return the next random number in AX.
;_rand
xor     bh,bh
mov     bl,[0444]    ;_lastValues+20
mov     ax,[bx+0430]    ;_lastValues
add     bx,06
cmp     bx,14
jl      03F0            ;_next1rand
sub     bx,14
;_next1rand
add     ax,[bx+0430]    ;_lastValues
;Store the new random number (AX) in the last values history
mov     bl,[0444]    ;_lastValues+20
mov     [bx+0430],ax    ;_lastValues
;Increment our pointer to the oldest last value
inc     bx
inc     bx
cmp     bx,14
jl      0406            ;_next2rand
sub     bx,14
;_next2rand
mov     [0444],bl    ;_lastValues+20
ret
;Seed the random number generator using the system timer
;_seed
xor     ah,ah
int     1a              ;Get ticks since midnight in CX:DX
mov     [0430],dx       ;_lastValues
mov     ax,dx
xor     bx,bx
;_LCG
mov     dx,4e35
mul     dx
inc     ax
inc     bx
inc     bx
mov     [bx+0430],ax    ;_lastValues
cmp     bx,12
jl      0417            ;_LCG
or      ax,0001         ;LFG needs at least 1 odd initial value
mov     [bx+0430],ax    ;_lastValues
ret
;_lastValues
dw      0,0,0,0,0,0,0,0,0,0
db      0
;Get the cell data (CH=text column 0-39, CL=text row 0-24, SI=bitmap address)
;Returns a bit in AL
;_get_cell_data
push    cx
xor     ah,ah
mov     al,[077B]       ;_grid_size+0 (width)
mov     bl,8
div     bl
cmp     ah,0
jz      0458            ;+3
xor     ah,ah
inc     al
mul     cl
add     si,ax
xor     ah,ah
mov     al,ch
mov     bl,8
div     bl
xor     bh,bh
mov     bl,al
mov     al,[bx+si]
mov     cl,ah
shr     al,cl
and     al,1
pop     cx
ret
;Updates cell data (CH=text column 0-39, CL=text row 0-24, SI=bitmap address)
;Toggles bit at the referenced address; returns new state as a bit in AL
;_set_cell_data
push    cx
xor     ah,ah
mov     al,[077B]       ;_grid_size+0 (width)
mov     bl,8
div     bl
cmp     ah,0
jz      0485            ;+3
xor     ah,ah
inc     al
mul     cl
add     si,ax
xor     ah,ah
mov     al,ch
mov     bl,8
div     bl
xor     bh,bh
mov     bl,al
mov     al,[bx+si]
mov     cl,ah
mov     ah,1
shl     ah,cl
xor     al,ah
mov     [bx+si],al
shr     al,cl
and     al,1
pop     cx
ret
;Reveals a cell (CH=text column 0-39, CL=text row 0-24)
;Returns the number of adjacent mines in BP
;_reveal_cell
xor     bp,bp           ;BP=mines adjacent
mov     di,cx           ;DI=click location
mov     cx,-1           ;CH=ff, CL=ff
;_count_mine_loop
mov     dx,di           ;DX=click location (DH=column, DL=row)
add     dh,ch
cmp     dh,0
jl      04D8            ;+14
cmp     dh,[077B]       ;_grid_size+0 (width)
jge     04D8            ;+12
add     dl,cl
cmp     dl,0
jl      04D8            ;+9
cmp     dl,[077C]       ;_grid_size+1 (height)
jge     04D8            ;+7
mov     si,0780         ;_grid_mines
xchg    cx,dx           ;CX=position to check, DX=counters
call    0445            ;_get_cell_data
mov     cx,dx           ;CX=counters
xor     ah,ah
add     bp,ax
inc     ch              ;increment column
cmp     ch,1
jle     04AE            ;_count_mine_loop
mov     ch,ff
inc     cl
cmp     cl,1
jle     04AE            ;_count_mine_loop
mov     ax,bp           ;AX=number of adjacent mines
;shl    ax,5            ;multiply by 32 (sprite size)
db      c1,e0,05
mov     si,05C8         ;_sprite_0
add     si,ax           ;calculate offset of sprite
mov     cx,di           ;CX=click location (CH=column, CL=row)
mov     dl,19           ;25 rows
sub     dl,[077C]       ;_grid_size+1 (height)
shr     dl,1            ;divide by 2
mov     dh,28           ;40 columns
sub     dh,[077B]       ;_grid_size+0 (width)
shr     dh,1            ;divide by 2
add     dx,cx
mov     ax,2
int     33              ;Hide mouse cursor
call    0535            ;_draw_sprite
mov     ax,1
int     33              ;Show mouse cursor
mov     si,0800         ;_grid_revealed
call    0472            ;_set_cell_data
;Check if the opened cell had a flag
mov     si,07C0         ;_grid_flags
call    0445            ;_get_cell_data
cmp     al,0
jz      0529            ;+3
mov     si,07C0         ;_grid_flags
call    0472            ;_set_cell_data
cmp     bp,0
jnz     0534            ;+4
;Toggle a flag on the revealed cell to indicate that it needs to be opened
mov     si,07C0         ;_grid_flags
call    0472            ;_set_cell_data
ret
;Draw a sprite (DH=text column 0-39, DL=text row 0-24, SI=address of sprite)
;Sprites are in EGA (G,B,R,I bitmask) format
;_draw_sprite
mov     ax,a000         ;EGA/VGA video RAM segment
mov     es,ax
mov     al,dl
;shl    al,3            ;multiply by 8
db      c0,e0,03
mov     dl,28
mul     dl
mov     dl,dh
xor     dh,dh
add     ax,dx
mov     bx,ax           ;BX=starting address of sprite
mov     dx,03c4
mov     al,02
out     dx,al           ;select EGA map mask register
;DX=port address, AL=EGA bit plane (1=blue, 2=green, 4=red, 8=intensity)
inc     dx
mov     al,1
out     dx,al
mov     ah,8            ;AH=counter
mov     di,bx           ;ES:DI=address in EGA video memory
movsb                   ;copy byte from DS:SI (sprite RAM) to ES:DI (video RAM)
add     di,27           ;move video address to same column of next row
dec     ah
jnz     0559            ;-3
shl     al,1
cmp     al,10
jnz     0554            ;-9
ret
;_cursor_masks
dw      3fff,1fff,0fff,07ff,03ff,07ff,03ff,c3ff
dw      c3ff,ffff,ffff,ffff,ffff,ffff,ffff,ffff
dw      0000,4000,6000,7000,7800,7000,1800,1800
dw      0000,0000,0000,0000,0000,0000,0000,0000
;_sprite_s
db      fe,fc,fc,fc,fc,fc,80,00,fe,fc,fc,fc,fc,fc,80,00
db      fe,fc,fc,fc,fc,fc,80,00,ff,83,83,83,83,83,ff,ff
;_sprite_0
db      fe,fe,fe,fe,fe,fe,fe,00,fe,fe,fe,fe,fe,fe,fe,00
db      fe,fe,fe,fe,fe,fe,fe,00,01,01,01,01,01,01,01,ff
;_sprite_1
db      fe,fe,fe,fe,fe,fe,fe,00,fe,f6,e6,f6,f6,f6,fe,00
db      fe,f6,e6,f6,f6,f6,fe,00,01,01,01,01,01,01,01,ff
;_sprite_2
db      fe,c6,fa,e6,de,c2,fe,00,fe,fe,fe,fe,fe,fe,fe,00
db      fe,c6,fa,e6,de,c2,fe,00,01,01,01,01,01,01,01,ff
;_sprite_3
db      fe,fe,fe,fe,fe,fe,fe,00,fe,fe,fe,fe,fe,fe,fe,00
db      fe,c6,fa,e6,fa,c6,fe,00,01,01,01,01,01,01,01,ff
;_sprite_4
db      fe,ea,da,c2,fa,fa,fe,00,fe,ea,da,c2,fa,fa,fe,00
db      fe,fe,fe,fe,fe,fe,fe,00,01,01,01,01,01,01,01,ff
;_sprite_5
db      fe,fe,fe,fe,fe,fe,fe,00,fe,c6,de,c6,fa,c6,fe,00
db      fe,fe,fe,fe,fe,fe,fe,00,01,01,01,01,01,01,01,ff
;_sprite_6
db      fe,e6,de,c6,da,e6,fe,00,fe,fe,fe,fe,fe,fe,fe,00
db      fe,fe,fe,fe,fe,fe,fe,00,01,01,01,01,01,01,01,ff
;_sprite_7
db      fe,c2,fa,f6,f6,f6,fe,00,fe,c2,fa,f6,f6,f6,fe,00
db      fe,c2,fa,f6,f6,f6,fe,00,01,3d,05,09,09,09,01,ff
;_sprite_8
db      fe,e6,da,e6,da,e6,fe,00,fe,e6,da,e6,da,e6,fe,00
db      fe,e6,da,e6,da,e6,fe,00,01,01,01,01,01,01,01,ff
;_sprite_f
db      fe,fc,c4,e4,f4,fc,80,00,fe,fc,c4,e4,f4,fc,80,00
db      fe,fc,fc,fc,fc,fc,80,00,ff,83,83,83,83,83,ff,ff
;_sprite_x
db      00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
db      fe,e6,ee,c6,82,82,c6,00,01,01,01,01,21,01,01,ff
;_sprite_b
db      fe,e6,ee,c6,82,82,c6,00,fe,e6,ee,c6,82,82,c6,00
db      fe,e6,ee,c6,82,82,c6,00,01,01,01,01,21,01,01,ff
;_sprite_e
db      fe,e6,ee,fe,ba,ee,c6,00,fe,e6,ee,fe,ba,ee,c6,00
db      fe,e6,ee,fe,ba,ee,c6,00,01,c7,6d,39,39,6d,c7,ff
;_lose_message
db      "GAME OVER$"
;_win_message
db      "YOU WIN!$"
;Width, height, number of mines (hex)
;_grid_size
;Beginner (8x8, 10 mines)
;db      8,8,a
;Intermediate (16x16, 40 mines)
;db      10,10,28
;Expert (30x16, 99 mines)
db    1e,10,63
;Number of non-mine cells left to uncover (-1=uninitialized, 0=win)
;_cells_remaining
dw      ffff
;Mines, flags, and revealed bitmaps
;Each bitmap needs to be at least height * ceil(width / 8) bytes in size
;_grid_mines
db      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;_grid_flags
db      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;_grid_revealed
db      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
db      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

rcx
740
nmines.com
w
q

If you pipe that into debug it'll produce a .com
 
I'd hazard that's why it's broken. Use labels!
I was using debug to assemble it, so the "label" is in the comment. I wrote something that updates all of the addresses in the code using the debug output. Any comment that starts in _ is a label, the corresponding 4-digit hex address on that line needs to be updated, and simple calculations can be done, e.g. ;_grid_size+1.

It's working as it is, but I wanted to add the feature where pressing both mouse buttons would clear the surrounding cells if you've got all the adjacent flags marked.

1724428723740.png
 
Last edited:
If you want a native UI you can use something cross-platform like GTK (native? on Linux but not on Mac or windows) or use whatever windows/mac provides but it would be non-portable to the other systems.
Qt6 defaults make it look like native windowing now, and even before that it was the best looking one. It's what I would recommend.

The only downside is that there's some complexity navigating Qt's memory management since it predates C++ smart pointers. It's its whole other system. A QObject owns its pointers and its children's pointers. Mixing shared_ptr or unique_ptr with that will accidentally share ownership and lead to double frees. Just stick with Qt's smart pointer system to avoid headaches (weak_ptr is okay, but QPointer is the same thing so you might as well use that.)
 
I was using debug to assemble it, so the "label" is in the comment. I wrote something that updates all of the addresses in the code using the debug output.
That's really cool. Though I'd be looking to use GAS and LD if I were doing this, so you can have labels and macros, etc. - they're an important part of assembly, after all. You might need a simple linker script, I'm not sure it understands COM directly.

If you've not seen it yet, the osdev.org wiki is really good for anything low-level like this.
 
  • Like
Reactions: UERISIMILITUDO
I was using debug to assemble it, so the "label" is in the comment. I wrote something that updates all of the addresses in the code using the debug output. Any comment that starts in _ is a label, the corresponding 4-digit hex address on that line needs to be updated, and simple calculations can be done, e.g. ;_grid_size+1.
As Rusty said, you really should use an assembler that supports labels since assemblers can and will use longer/shorter versions of instructions with the same mnemonic.
Some assemblers even have pseudo-mnemonics, like those for RISC-V with e.g. li which may emit any number of instructions. Though I think x86 doesn't have any.

Also
Code:
;shr cx,4 ;divide by 16
db c1,e9,04
;shr dx,3 ;divide by 8
db c1,ea,03
This is extremely sketchy. What are you trying to achieve with this?
 
--Last words of every subpar programmer on an ego trip
I'm (mostly) joking in my original post, but you're correct. I don't want to harm the cohesion of the group. Even though I could pull rank, actually pulling rank would be a dick move. The reason I want to move from an engine and into C++ and OpenGL is because this whole thing is just a hobby and I want the learning experience without spending time with money on the line. But I still want it to be fun for everyone else because they contribute stuff I can't do myself.
 
I'm (mostly) joking in my original post, but you're correct. I don't want to harm the cohesion of the group. Even though I could pull rank, actually pulling rank would be a dick move. The reason I want to move from an engine and into C++ and OpenGL is because this whole thing is just a hobby and I want the learning experience without spending time with money on the line. But I still want it to be fun for everyone else because they contribute stuff I can't do myself.
Why do your teammates not like the idea of using a custom engine? Uncertainty in your skills? Bad tooling? Porting concerns? Maybe if you address their fears, they will be more receptive to your plans.

Make sure your engine is simple to understand and easy to use, to reduce how difficult it is to adjust to. This probably depends on what your team actually does. If the model maker can export his models (and associated bullshit data) to a standard format and your engine can load those models, I don't think he will care much about what happens after that, as long as his model still looks good. You might have to worry about level designers, if you have them. They will need some basic tools to do their job. Maybe make a shitty Blender script that converts simple meshes into level collision shapes and turns certain specially-named Empty objects into engine-specific entities, then serialize that to whatever bizarre format you find easiest to load from the C++ side. Then you can make a proper level editor inside the engine. If you can end up making things easier for people in your engine than whatever you used to use, you are doing extremely well.

Also try redpilling them on why custom engines are based as fuck, because they are.
 
So I'm briefly unfurloughed because turns out I'm more important to the business than I/they realized. I'm pretty annoyed at them and I should probably brush off my resume and start looking for somewhere better.

Anyway now that I'm back at work I'm doing a little bit with git automation in Golang, and lol, this made me laugh.

For those who aren't aware, there's been a trend recently for woke language scolds in software have been trying to get rid of words like "whitelist" and "blacklist" because of apparently implicit racism or some shit.

"Master" is on their shitlist. "What, like slavemaster??"

I'm not kidding, this is why the default branch name has changed on github from master to main.

So it's funny to see that there's a currently-maintained library still using the word "master". Countdown until they deprecate this.
 
Why do your teammates not like the idea of using a custom engine? Uncertainty in your skills? Bad tooling? Porting concerns? Maybe if you address their fears, they will be more receptive to your plans.

Make sure your engine is simple to understand and easy to use, to reduce how difficult it is to adjust to. This probably depends on what your team actually does. If the model maker can export his models (and associated bullshit data) to a standard format and your engine can load those models, I don't think he will care much about what happens after that, as long as his model still looks good. You might have to worry about level designers, if you have them. They will need some basic tools to do their job. Maybe make a shitty Blender script that converts simple meshes into level collision shapes and turns certain specially-named Empty objects into engine-specific entities, then serialize that to whatever bizarre format you find easiest to load from the C++ side. Then you can make a proper level editor inside the engine. If you can end up making things easier for people in your engine than whatever you used to use, you are doing extremely well.

Also try redpilling them on why custom engines are based as fuck, because they are.
I should just ask flat-out why they aren't receptive to the idea, but from what I can infer it's because they've internalized the idea common on certain corners of the internet that creating your own engine is bad and that you'll never release anything if you do that. I think another part of it is that they want something proven before they commit to it, but I want to push myself to do stuff I've never done before.
I know that two people on the team are most familiar with Unity and they want to use it because they're resistant to learning anything new. I dragged them kicking and screaming into Godot because I hate Unity for a number reasons, but I know that they want to go back. I can feel that they're expecting to return to Unity at some point. I think you're right that I just need to build something and show them that it can be better.

I have more reasons why I want to build my own game engine other than learning and pushing myself, including my dislike of modern graphics rendering trends and funky technology I want to build, but education and fun is the big reason. None of us are getting paid so the burn rate of this whole operation is $0 a year. Why shouldn't I use this opportunity to improve myself?

I'm not kidding, this is why the default branch name has changed on github from master to main.
I went into github and changed the default back to master for this very reason.
 
I should just ask flat-out why they aren't receptive to the idea, but from what I can infer it's because they've internalized the idea common on certain corners of the internet that creating your own engine is bad and that you'll never release anything if you do that. I think another part of it is that they want something proven before they commit to it, but I want to push myself to do stuff I've never done before.
Perhaps you should first show them a working port of the game to your own engine, complete with features, fixes, and polish not present on the previous engine. It will take a lot of work, but it will pay off, and that work needed to be done anyway. The difference is presentation. Seeing the game in a better state in your new engine will make a much-needed good first impression. They would feel silly saying "you'll never finish a game you make in your own engine" if you literally just showed them a better version of a game they worked on, as ported to your new engine.
 
Perhaps you should first show them a working port of the game to your own engine, complete with features, fixes, and polish not present on the previous engine. It will take a lot of work, but it will pay off, and that work needed to be done anyway. The difference is presentation. Seeing the game in a better state in your new engine will make a much-needed good first impression. They would feel silly saying "you'll never finish a game you make in your own engine" if you literally just showed them a better version of a game they worked on, as ported to your new engine.
I don't want to move the current game into a custom engine, this is more a plan for future games. The current game is doing fine in Godot.
And the thing is, there is no engine to port it to. That's the point. I want to make games without the engine and make the choices about tooling that fit the game as we build it.
 
I don't want to move the current game into a custom engine, this is more a plan for future games. The current game is doing fine in Godot.
And the thing is, there is no engine to port it to. That's the point. I want to make games without the engine and make the choices about tooling that fit the game as we build it.
It still might be wise to make use of your current assets and build a tiny version of your current game. Even if you don't re-use any code for your next C++/OpenGL game (doubtful) you'll probably learn a lot of shit anyway. No need to wait until you have a bunch of people counting on you.
 
It still might be wise to make use of your current assets and build a tiny version of your current game. Even if you don't re-use any code for your next C++/OpenGL game (doubtful) you'll probably learn a lot of shit anyway. No need to wait until you have a bunch of people counting on you.
Good point. I'd get a lot of ground-work out of the way for future games doing this.
 
Good point. I'd get a lot of ground-work out of the way for future games doing this.
You can even bundle a bunch of that code into a library of sorts that lets you write games without worrying about tricky things like setting up event loops or wrangling GL. Maybe also write some generic tools that can be used to create data in formats the library understands, so you and your teammates can define certain in-game structures without having to manually write a bunch of source code that just initializes a bunch of objects and sets all their properties. The tools could generate such source code instead of making serialized data files, but that's just an implementation detail.

Anyway, you could call this library and the associated data editors a "game engine", since it's the core piece of machinery needed to make any of your games work. Maybe having a game engine isn't necessarily bad, you just personally want a very minimal one that you made yourself and can modify for each of your games as you wish.
 
You can even bundle a bunch of that code into a library of sorts that lets you write games without worrying about tricky things like setting up event loops or wrangling GL. Maybe also write some generic tools that can be used to create data in formats the library understands, so you and your teammates can define certain in-game structures without having to manually write a bunch of source code that just initializes a bunch of objects and sets all their properties. The tools could generate such source code instead of making serialized data files, but that's just an implementation detail.

Anyway, you could call this library and the associated data editors a "game engine", since it's the core piece of machinery needed to make any of your games work. Maybe having a game engine isn't necessarily bad, you just personally want a very minimal one that you made yourself and can modify for each of your games as you wish.
I don't think having an engine is bad. I want an engine, but as you describe I want it to be a thin layer built up organically over time that I understand and control, rather than a black box designed to facilitate a wide range of games. At this level the line between what is the game engine and what is the game gets blurry, which is where I like it.
 
Back