User Tools

Site Tools


sd:part_ii_writing_games_in_assembly_language

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
sd:part_ii_writing_games_in_assembly_language [2026/04/02 19:41] appledogsd:part_ii_writing_games_in_assembly_language [2026/04/03 05:30] (current) appledog
Line 3: Line 3:
  
 == Introduction == Introduction
-At the end of [[SD-8516 Stellar BASIC]] we wrote a game called [[sdb:robots|ROBOTS.BAS]]. This was a fun little take on the classic CHASE or 'robots' game from the bsd games collection. Now, for our study of Assembly Language, let's write a similar game: 'robots.asm'.+At the end of [[SD-8516 Stellar BASIC]] we wrote a game called [[sdb:robots|ROBOTS.BAS]]. This was a fun little take on the classic CHASE or 'robots' game from the bsd games collection. Now, for our study of Assembly Language, let's write a similar game: 'robots.asm'. Don't worry if you're not familiar with the BASIC version of this program; everything will be explained here.
  
 == Part 1: Assembling and Running a Program == Part 1: Assembling and Running a Program
-An assembly language program should start with an .address the bytes will be compiled fromOur program therefore begins:+Just like BASIC programs have line numbers, or C programs have #include statements, an assembly language program should start with an ''.address'' statementThis will tell the assembler where to start assembling the program. This enables us to use labels like ''start:'' and ''message:''. The assembler can calculate the exact address of the label in relative to the ''.address'' when assembling the program.
  
 <codify armasm> <codify armasm>
Line 216: Line 216:
  
 more to come... more to come...
 +
 +== Part 3: Player Input
 +Let's begin part 3 by adding a new subroutine to our main loop. Our main loop now becomes:
 +
 +<codify armasm>
 +main_loop:
 +    CALL @draw_map
 +    CALL @get_input
 +    RET
 +</codify>
 +
 +=== get_input
 +The primary goal of this section is to get input from the player and deal with it. We can do this by using the getkey function:
 +
 +<codify armasm>
 +get_input:
 +    LDAH $02        ; getkey()
 +    INT $10
 +</codify>
 +
 +In this case, the function specification for AH=$02, INT 0x10 is:
 +
 +    ; ============================================================================
 +    ; AH=02h - Read Character (Blocking)
 +    ; Input:  None
 +    ; Output: AL  = ASCII character
 +    ;          = number of keys that were in buffer before this call
 +    ;          = keyboard flags at time of press
 +    ; Note:   X, Y preserved for cursor position
 +    ;         This function BLOCKS until a key is pressed
 +    ; ============================================================================
 +
 +As we can see, this function returns the ASCII code of the key the player will press in ''AL''. Thus, we can deal with the player's commands.
 +
 +=== uppercase or lowercase?
 +The player might type an uppercase command or a lowercase command. Let's normalize the keys to uppercase before processing them:
 +
 +<codify armasm>
 +
 +    ; Uppercase: if AL >= 'a', it must be an uppercase character (or an invalid command).
 +    CMP AL, #97
 +    JNC @gi_check_keys      ; AL < 'a', skip
 + 
 +    CMP AL, #123
 +    JC @gi_check_keys       ; AL >= '{', skip
 +    
 +    SUB AL, #32
 +    
 +gi_check_keys:
 +    ...
 +</codify>
 +
 +CMP works as follows:
 +
 +    CMP A, B        ; if A >= B, then set carry
 +
 +Therefore,
 +
 +    CMP AL, #97     ; if AL is greater or equal to #97 ('a') then set carry
 +
 +So therefore if carry is NOT set, skip past the SUB command. Or else (if it's a lowercase ASCII) subtract 32 to convert from lowercase to uppercase.
 +
 +The second compare has a protective function.
 +
 +    CMP AL, #123             ; if AL >= 123, set carry.
 +    
 +    ; If it's '{' or anything after, skip:
 +    JC @gi_check_keys        ; Jump if Carry = Jump if AL > 'z' (al >= '}')
 +
 +
 +So after these two checks, the only values that reach SUB AL, #32 are exactly the bytes from 97 to 122 inclusive; i.e. 'a' to 'z'.
 +
 +Visual summary:
 +^ AL Value ^ Meaning ^ What Happens ^
 +| < 97 | before ''a'' | Skipped. |
 +| 97-122 | ''a'' to ''z'' | SUB #32 becomes 'A' to 'Z'. |
 +| >= 123 | after 'z'\\ //'}' and up// | Skipped. |
 +
 +=== Processing player input
 +We will use the HJKL convention:
 +
 +<codify armasm>
 +gi_check_keys:
 +    CMP AL, #'H'
 +    JZ @move_left
 +
 +    CMP AL, #'J'
 +    JZ @move_down
 +
 +    CMP AL, #'K'
 +    JZ @move_up
 +
 +    CMP AL, #'L'
 +    JZ @move_right
 +
 +    CMP AL, #'Q'
 +    JZ @quit_game
 +
 +    RET
 +</codify>
 +
 +This is easy enough; after a CMP, if the values are equal then the zero flag is set. We will use JZ (jump if zero flag is set) to go to the correct routine.
 +
 +=== processing each command
 +<codify armasm>
 +move_left:
 +    LDAL [@PX]        ; load variable PX into register AL.
 +    DEC AL            ; X = X - 1 (move to the left!)
 +    
 +    CMP AL, #1        ; bounds check. Is the player on the border?
 +    JC @ml_ok         ; AL >= 1, so it's ok. skip to ml_ok,
 +    
 +    LDAL #1           ; If  we reach here the player was on the border; set position to 1.
 +    
 +ml_ok:
 +    STAL [@PX]        ; pass! Save the player's location.
 +    RET
 +</codify>
 +
 +This is the move_left command. We begin by loading the player's X location into AL and executing the move. After a bounds check, we save the variable. All of the other moves operate this way.
sd/part_ii_writing_games_in_assembly_language.1775158901.txt.gz · Last modified: by appledog

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki