Annotation of os2sdk/demos/apps/life/life2.asm, revision 1.1.1.1

1.1       root        1: ;***   life2.asm - assembler routines for life.c
                      2: ;*
                      3: ;*     Contains:       _draw_grid - draws 79x45 grid on screen
                      4: ;*                     _dostep    - advances the internal and screen grids
                      5: ;*                                      one generation
                      6: ;*                     scrfill    - private screen routine for _dostep
                      7: ;*                     scrremove  - private screen routine for _dostep
                      8: ;*
                      9: 
                     10: 
                     11: ;***   segment definitions for the link with C
                     12: ;
                     13: _TEXT  SEGMENT  BYTE PUBLIC 'CODE'
                     14: _TEXT  ENDS
                     15: _DATA  SEGMENT  WORD PUBLIC 'DATA'
                     16: _DATA  ENDS
                     17: CONST  SEGMENT  WORD PUBLIC 'CONST'
                     18: CONST  ENDS
                     19: _BSS   SEGMENT  WORD PUBLIC 'BSS'
                     20: _BSS   ENDS
                     21: DGROUP GROUP   CONST, _BSS, _DATA
                     22:        ASSUME  CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP
                     23: 
                     24: ;***   the public routines
                     25: ;
                     26:        PUBLIC  _draw_grid, _dostep
                     27: 
                     28: 
                     29: ;***   Global variables from LIFE.C
                     30: ;
                     31:        EXTRN   _ScrSeg:WORD
                     32:        EXTRN   _ScrCol:WORD
                     33:        EXTRN   _ScrRow:WORD
                     34: 
                     35: ;***   OS/2 functions
                     36: ;
                     37:        EXTRN   VIOSCRUNLOCK:FAR
                     38:        EXTRN   VIOSCRLOCK:FAR
                     39: 
                     40: 
                     41: _TEXT     SEGMENT
                     42: ;***   _draw_grid - clears screen and draws 79x45 grid
                     43: ;*
                     44: ;*     Entry:  ds:_ScrSeg - screen buffer segment, from life.c
                     45: ;*
                     46: ;*     Exit:   None
                     47: ;*
                     48: _draw_grid     PROC NEAR
                     49:        push    bp                      ; startup
                     50:        mov     bp,sp
                     51:        sub     sp,2                    ; one word variable for VIOSCRLOCK
                     52:        push    di                      ; save register used by C compiler
                     53: 
                     54: ;      get screen access
                     55:        mov     ax,1
                     56:        push    ax                      ; wait until screen available
                     57:        lea     ax,byte ptr [bp-2]
                     58:        push    ss
                     59:        push    ax                      ; far address of return code
                     60:        sub     ax,ax
                     61:        push    ax                      ; reserved word
                     62:        call    VIOSCRLOCK              ; call DOS for access
                     63: 
                     64: ;      get parameter and set up
                     65:        mov     es,ds:_ScrSeg           ; (es) = screen buffer segment
                     66:        xor     di,di                   ; (di) = offset in screen (start at 0)
                     67: 
                     68: ;      loop to draw 45 rows of the tops and middles of grid squares
                     69:        mov     dx,45                   ; (dx) = rows of grid squares, counter
                     70: dg1:   mov     ax,5555h                ; (ax) = alternating bit pattern
                     71:        mov     cx,39                   ; (cx) = number of full words on a line
                     72:        rep     stosw                   ; fill line with 5555h
                     73:        mov     es:[di],al              ; finish off last odd byte
                     74:        inc     di                      ; (di) = start of next row
                     75:        inc     di
                     76:        mov     ax,08080h               ; (ax) = left bit on
                     77:        mov     cx,40                   ; (cx) = number of words on a line
                     78:        rep     stosw                   ; fill next line with f0f0h
                     79:        dec     dx                      ; at screen bottom?
                     80:        jnz     dg1                     ; if no, loop
                     81: 
                     82: ;      draw the last line
                     83:        mov     ax,5555h                ; (ax) = alternating bits
                     84:        mov     cx,39                   ; (cx) = full words on last line
                     85:        rep     stosw                   ; do fill
                     86:        mov     es:[di],al              ; finish off line with odd byte
                     87: 
                     88: ;      clear bottom on screen on even bit plane
                     89:        inc     di                      ; (di) = start of last few lines
                     90:        sub     ax,ax                   ; (ax) = blank
                     91:        mov     cx,400                  ; (cx) = words left at bottom
                     92:        rep     stosw
                     93: 
                     94: ;      draw the grid lines on the odd bit plane
                     95:        mov     di,2000h                ; (di) = top of odd bit plane
                     96:        mov     ax,08080h               ; (ax) = left bit on
                     97:        mov     cx,40*2*45              ; (cx) = words to fill
                     98:        rep     stosw                   ; fill remainder with f0f0h
                     99: 
                    100: ;      clear bottom on screen on odd bit plane
                    101:        sub     ax,ax                   ; (ax) = blank
                    102:        mov     cx,400                  ; (cx) = words left at bottom
                    103:        rep     stosw
                    104: 
                    105: ;      return the screen
                    106:        sub     ax,ax
                    107:        push    ax                      ; reserved word
                    108:        call    VIOSCRUNLOCK            ; call DOS to return screen
                    109: 
                    110: ;      return
                    111:        pop     di
                    112:        mov     sp,bp
                    113:        pop     bp
                    114:        ret
                    115: _draw_grid     ENDP
                    116: 
                    117: 
                    118: ;***   _dostep - advances InGrid one generation.
                    119: ;*
                    120: ;*     Entry:  char far *INGRID - InGrid, main internal bit map of cells
                    121: ;*             char far *INGRID2 - InGrid2, working area of same size
                    122: ;*             unsigned INROW - InRow, bits per row of above to areas
                    123: ;*             unsigned INCOL - InCol, rows of above to areas
                    124: ;*             ds:_ScrSeg       - from life.c
                    125: ;*             ds:_ScrRow       - from life.c
                    126: ;*             ds:_ScrCol       - from life.c
                    127: ;*
                    128: ;*     Exit:   InGrid is updated on generation in accordance with
                    129: ;*             the rules of life.
                    130: ;*             Returns in AX the return code from its VIOSCRLOCK call
                    131: ;*
                    132: INGRID EQU [bp+4]
                    133: INGRID2 EQU [bp+8]
                    134: INROW EQU [bp+12]
                    135: INCOL EQU [bp+14]
                    136: 
                    137: _dostep PROC   NEAR
                    138:        push    bp
                    139:        mov     bp,sp
                    140:        sub     sp,2                    ; make room for local var
                    141:        push    di
                    142:        push    si
                    143:        push    es
                    144:        push    ds
                    145: 
                    146:        ; try to lock screen and put return code in [BP-2]
                    147:        xor     ax,ax
                    148:        push    ax                      ; don't wait until screen available
                    149:        lea     ax,byte ptr [bp-2]
                    150:        push    ss
                    151:        push    ax                      ; far address of return code
                    152:        sub     ax,ax
                    153:        push    ax                      ; reserved word
                    154:        call    VIOSCRLOCK              ; call DOS for access
                    155: 
                    156:        ; get pointers to the two internal grids
                    157:        les     di,INGRID2               ; (es:di) = @InGrid2
                    158:        lds     si,INGRID               ; (ds:si) = @InGrid
                    159: 
                    160:        ; copy InGrid into InGrid2
                    161:        mov     ax,INCOL              ; (ax) = cells per row
                    162:        mul     word ptr INROW        ; (ax) = total cells
                    163:        mov     cl,4
                    164:        shr     ax,cl                   ; (ax) = cell/16 = total words
                    165:        mov     cx,ax                   ; (cx) = total words
                    166:        rep     movsw                   ; move InGrid into InGrid2
                    167: 
                    168: 
                    169:        ; main step loop
                    170:        ;   I use a rather odd algorithm.  "neighbors" is defined
                    171:        ;   here as all cells in a 3x3 grid summed.  If neighbors < 3, the
                    172:        ;   the cell in the center is turned off.  If neighbors = 3, the cell
                    173:        ;   is turned on.  If neighbors = 4, the cell is left in its current
                    174:        ;   state.  If neighbors > 4, the cell is turned off.
                    175:        push    ds
                    176:        pop     es                      ; (es) = InGrid's segment
                    177:        lds     bx,INGRID2               ; (ds) = InGrid2's segment
                    178:                                        ; (bx) = pointer to offset in both
                    179:        mov     di,INROW              ; (di) = row count
                    180:        mov     si,INCOL              ; (si) = column count
                    181:        shr     si,1
                    182:        shr     si,1
                    183:        shr     si,1                    ; (si) = bytes per row in grids
                    184: 
                    185:        ; loop within the grid through all its rows
                    186:        ;    here we come when at the start of a row
                    187: ds1:   mov     cx,INCOL              ; (cx) = column count
                    188:        mov     al,80h                  ; (al) = bit mask for current bit
                    189:        xor     dx,dx                   ; (dh) = #of neighbors 1 col back
                    190:                                        ; (dl) = #of neighbors at cur col
                    191: 
                    192:        ; get number of neighbors on current row
                    193: ds2:   xor     ah,ah                   ; (ah) = count of neighbors on cur row
                    194:        test    ds:[bx],al              ; is current bit on?
                    195:        jz      ds3                     ; if not go on
                    196:        inc     ah                      ; if yes, inc neighbor count
                    197: ds3:   cmp     bx,si                   ; are we on top row
                    198:        jb      ds4                     ; if yes, don't check above top
                    199:        push    bx                      ; save bx
                    200:        sub     bx,si                   ; backup bx to previous row
                    201:        test    ds:[bx],al              ; is up a row bit on?
                    202:        pop     bx                      ; restore bx
                    203:        jz      ds4                     ; if not go on
                    204:        inc     ah                      ; if yes, inc neighbor count
                    205: ds4:   cmp     di,1                    ; are we on last row?
                    206:        jz      ds5                     ; if yes, don't read off edge
                    207:        test    ds:[bx+si],al           ; is bit down a row on?
                    208:        jz      ds5                     ; if not, go on to final neighbor addin
                    209:        inc     ah                      ; if yes, inc neighbor count
                    210: 
                    211:        ; add up the total number of neighbors and decide what to do
                    212: ds5:   cmp     cx,INCOL                ; are we at far left?
                    213:        jz      ds12                    ; if yes, don't affect bits off edge
                    214:        add     dh,dl                   ; (dh) = previous two rows of neighbors
                    215:        add     dh,ah                   ; (dh) = total neighbor count
                    216:        cmp     dh,3
                    217:        jb      ds6                     ; if neighbors <3, turn off the cell
                    218:        je      ds9                     ; if neighbors = 3, turn on the cell
                    219:        cmp     dh,4                    ;
                    220:        je      ds12                    ; if neighbors = 4, do nothing
                    221: 
                    222:        ; turn off the center bit
                    223: ds6:   rol     al,1                    ; backup to center bit
                    224:        jnc     ds7                     ; if no overflow, go on
                    225:        dec     bx                      ; else, backup to last byte
                    226: ds7:   test    es:[bx],al              ; is it already off
                    227:        jz      ds8                     ; if yes, don't do it again
                    228:        not     al                      ; turn on all bits but one to blank
                    229:        and     es:[bx],al              ; force off bit in InGrid
                    230:        not     al                      ; restore al
                    231: 
                    232:        pop     ds                      ; (ds) =  C's data ptr
                    233:        call    scrremove               ; turn off on screen
                    234:        push    ds                      ; resave C's data ptr
                    235:        mov     ds,[bp+8+2]             ; (ds) = seg of InGrid2
                    236: 
                    237: ds8:   ror     al,1                    ; put back al to foreward bit
                    238:        jnc     ds12                    ; if no overflow, go to next bit
                    239:        inc     bx                      ; if overflow, restore bx
                    240:        jmp     ds12                    ; go on to next bitl
                    241: 
                    242:        ; turn on the center bit
                    243: ds9:   rol     al,1                    ; backup to center bit
                    244:        jnc     ds10                    ; if no overflow, go on
                    245:        dec     bx                      ; else, backup to last byte
                    246: ds10:  test    es:[bx],al              ; is it already on?
                    247:        jnz     ds11                    ; if yes, don't do it again
                    248:        or      es:[bx],al              ; force on bit in InGrid
                    249:        pop     ds                      ; (ds) =  C's data ptr
                    250:        call    scrfill                 ; turn on on screen
                    251:        push    ds                      ; resave C's data ptr
                    252:        mov     ds,[bp+8+2]             ; (ds) = seg of InGrid2
                    253: ds11:  ror     al,1                    ; put back al to foreward bit
                    254:        jnc     ds12                    ; if no overflow, go to next bit
                    255:        inc     bx                      ; if overflow, restore bx
                    256: 
                    257:        ; advance to the next bit
                    258: ds12:  ror     al,1                    ; (al) mask advances to next bit
                    259:        mov     dh,dl                   ; move done neighbor count
                    260:        mov     dl,ah                   ; move the new neighbor row into bl
                    261:        jnc     ds13                    ; if still in same byte, jmp
                    262:        inc     bx                      ; if at byte end, advance to next byte
                    263: ds13:  loop    ds2                     ; loop through rest of bits on line
                    264: 
                    265: 
                    266:        ; at the end of the row
                    267:        dec     di                      ; decrement row count
                    268:        jz      dsx                     ; if at end of grid, goto exit routine
                    269:        jmp     ds1                     ; if not at bottom, go to next row
                    270: 
                    271:        ; at the end of the grid
                    272:        ; return the screen
                    273: dsx:   cmp     byte ptr [bp-2],0       ; is the screen locked?
                    274:        jnz     dsx1                    ; if not, don't unlock
                    275: 
                    276:        sub     ax,ax
                    277:        push    ax                      ; reserved word
                    278:        call    VIOSCRUNLOCK            ; call DOS to return screen
                    279: 
                    280: dsx1:  xor     ah,ah
                    281:        mov     al,[bp-2]               ; return code from SCRLOCK
                    282: 
                    283:        pop     ds
                    284:        pop     es
                    285:        pop     si
                    286:        pop     di
                    287:        mov     sp,bp
                    288:        pop     bp
                    289:        ret
                    290: _dostep ENDP
                    291: 
                    292: 
                    293: ;***   scrfill - fills in a cell on the screen in 79x45 grid
                    294: ;*
                    295: ;*     Entry:  (di) = row number counted from bottom up (InRow-di=row to fill)
                    296: ;*             (cx) = col number from right-1 (InCol-1-cx = col to fill)
                    297: ;*             (ds) = data segment of life.c
                    298: ;*
                    299: ;*     Exit:   None, saves all registers
                    300: ;*
                    301: scrfill proc   near
                    302:        cmp     [bp-2],byte ptr 0       ; is the screen available?
                    303:        jnz     sfxx                    ; if not, exit
                    304: 
                    305:        push    es
                    306:        push    ax
                    307:        push    bx
                    308:        push    dx
                    309: 
                    310:        ; get screen pointer
                    311:        mov     es,ds:_ScrSeg           ; (es) = screen buf segment
                    312:        mov     ax,INROW
                    313:        sub     ax,di                   ; (ax) = row
                    314:        cmp     ax,ds:_ScrRow           ; is it on the screen?
                    315:        jae     sfx                     ; if off, exit
                    316:        mul     WORD PTR INCOL          ;        * InCol
                    317:        shl     ax,1                    ;        * 2
                    318:        mov     dx,INCOL
                    319:        sub     dx,cx
                    320:        dec     dx                      ;               (dx) = col to fill
                    321:        cmp     dx,ds:_ScrCol           ; is it on the screen?
                    322:        jae     sfx                     ; if off, exit
                    323:        add     ax,dx                   ;        + col = scrn offset of cell
                    324: 
                    325:        ; fill in screen cell
                    326:        mov     bx,ax                   ; (es:bx) = far ptr to screen cell
                    327:        mov     BYTE PTR es:[bx+2000h],7fh      ; first line of cell
                    328:        mov     BYTE PTR es:[bx+80],7fh         ; second
                    329:        mov     BYTE PTR es:[bx+2000h+80],7fh   ; third line of cell
                    330: 
                    331: sfx:   pop     dx
                    332:        pop     bx
                    333:        pop     ax
                    334:        pop     es
                    335: sfxx:  ret
                    336: scrfill endp
                    337: 
                    338: 
                    339: ;***   scrremove - removes a cell on the screen in 79x45 grid
                    340: ;*
                    341: ;*     Entry:  (di) = row number counted from bottom up (InRow-di=row to fill)
                    342: ;*             (cx) = col number from right-1 (InCol-1-cx = col to fill)
                    343: ;*             (ds) = data segment of life.c
                    344: ;*
                    345: ;*     Exit:   None, saves all registers
                    346: ;*
                    347: scrremove proc  near
                    348:        cmp     [bp-2],byte ptr 0       ; is the screen available?
                    349:        jnz     srxx                    ; if not, exit
                    350: 
                    351:        push    es
                    352:        push    ax
                    353:        push    bx
                    354:        push    dx
                    355: 
                    356:        ; get screen pointer
                    357:        mov     es,ds:_ScrSeg           ; (es) = screen buf segment
                    358:        mov     ax,INROW
                    359:        sub     ax,di                   ; (ax) = row
                    360:        cmp     ax,ds:_ScrRow           ; is it on the screen?
                    361:        jae     srx                     ; if off, exit
                    362:        mul     WORD PTR INCOL          ;        * InCol
                    363:        shl     ax,1                    ;        * 2
                    364:        mov     dx,INCOL
                    365:        sub     dx,cx
                    366:        dec     dx                      ;               (dx) = col
                    367:        cmp     dx,ds:_ScrCol           ; is it on the screen?
                    368:        jae     srx                     ; if off, exit
                    369:        add     ax,dx                   ;        + col = scrn offset of cell
                    370: 
                    371:        ; remove screen cell
                    372:        mov     bx,ax                   ; (es:bx) = far ptr to screen cell
                    373:        mov     BYTE PTR es:[bx+2000h],80h      ; first line of cell
                    374:        mov     BYTE PTR es:[bx+80],80h         ; second
                    375:        mov     BYTE PTR es:[bx+2000h+80],80h   ; third line of cell
                    376: 
                    377: srx:   pop     dx
                    378:        pop     bx
                    379:        pop     ax
                    380:        pop     es
                    381: srxx:  ret
                    382: scrremove endp
                    383: 
                    384: _TEXT  ENDS
                    385: END

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.