@program prog_code,prog_name include macros.h include controls.h ; Tile Slider v1.0 ; By Dave Jaklitsch ; Copyright © 1997 ; v1.0 released on 7/16/97 ; D. JacKaL's TI Terminal: for all TI graphing calcs: ; http://home.pb.net/~jaklitsch/djackal/ti.htm ; TI-Files: the biggest and best TI page on the 'net: ; http://ti-files.home.ml.org/ ; ; I'm writing this to learn 68K ASM. I don't know too much yet, so don't ; expect too much. Expect to see improved versions in the future, though, ; as well as other Fargo games written by me. Also, if any of this code ; turns out to be useful, then please feel free to take anything from it to ; use in your own programs. Please do not change anything in this program ; without my permission. ; ; ************** Start of Fargo prog ************** MAXSLTS equ 48 ;maximum number of slots COLSTRT equ 5 ;x coordinate of 1st row and column ROWSTRT equ 5 ;y coordinate of 1st row and column COLWTH equ 30 ;column width ROWHGT equ 20 ;row height prog_code: jsr flib[clr_scr] ;clear screen SetFont #2 ;macro.h stuff WriteStr #60,#10,#4,prog_name SetFont #1 WriteStr #10,#30,#4,author WriteStr #47,#45,#4,copy WriteStr #56,#100,#4,press jsr flib[idle_loop] ;pause main_menu: jsr flib[clr_scr] ;clear screen SetFont #2 ;macro.h stuff WriteStr #60,#10,#4,prog_name SetFont #1 WriteStr #75,#40,#4,new WriteStr #75,#50,#4,help WriteStr #75,#60,#4,about WriteStr #75,#70,#4,quit loop_menu: jsr flib[idle_loop] IfKey #268,get_nums ;start new game IfKey #269,game_help ;game help IfKey #270,game_info ;about IfKey #'q',end_game ;quit bra loop_menu game_help: jsr flib[clr_scr] ;clear screen SetFont #2 WriteStr #13,#10,#4,help1 SetFont #1 WriteStr #55,#40,#4,help2 WriteStr #55,#50,#4,help3 WriteStr #55,#60,#4,help4 WriteStr #43,#85,#4,help5 jsr flib[idle_loop] bra main_menu game_info: jsr flib[clr_scr] ;clear screen WriteStr #75,#30,#4,prog_name WriteStr #10,#40,#4,author WriteStr #47,#50,#4,copy WriteStr #50,#60,#4,about1 jsr flib[idle_loop] bra main_menu ; ***************** Generate Board *************************** get_nums: jsr flib[clr_scr] WriteStr #40,#48,#4,numcols WriteStr #40,#64,#4,numrows WriteStr #60,#90,#4,enter WriteStr #60,#100,#4,quit2 num_loop: moveq #0,d0 move.b ncols,d0 move.l #6,d1 move.l #20,d2 move.l #0,d4 jsr hexlib[put_hex] moveq #0,d0 move.b nrows,d0 move.l #8,d1 move.l #20,d2 move.l #0,d4 jsr hexlib[put_hex] jsr flib[idle_loop] IfKey #268,cols_down IfKey #272,cols_up IfKey #269,rows_down IfKey #273,rows_up IfKey #13,ready IfKey #113,main_menu bra num_loop cols_down: cmp.b #2,ncols beq num_loop subi.b #1,ncols bra num_loop cols_up: cmp.b #8,ncols beq num_loop addi.b #1,ncols bra num_loop rows_down: cmp.b #2,nrows beq num_loop subi.b #1,nrows bra num_loop rows_up: cmp.b #6,nrows beq num_loop addi.b #1,nrows bra num_loop ready: clr.l d5 clr.l d6 move.b nrows,d5 move.b ncols,d6 mulu d6,d5 move.w d5,nslots start_game: jsr flib[clr_scr] ;clear screen SetFont #0 WriteStr #38,#123,#1,prog_name WriteStr #108,#123,#1,copy lea slots,a0 ;initialize the slots vector; set each slot move.w nslots,d5 subi.w #1,d5 move.w d5,d0 ; to -1 to mark it unoccupied addi.w #1,d0 zero_slots: move.b #-1,0(a0,d0) dbf.w d0,zero_slots clr.l d0 move.w nslots,d0 ;find a random slot and make it the space jsr flib[random] ; Note: 0 is used to mark the space move.b #0,0(a0,d0.w) move.w d0,spslotofs ;save offset to slot occupied by the space move.l d0,d2 clr.l d5 move.b ncols,d5 divu.w d5,d2 move.w d2,yspace ;save initial row# of the space swap d2 move.w d2,xspace ;save initial col# of the space move.w nslots,d5 subi.w #2,d5 move.w d5,d1 ;initialize the remaining slots in random rand_num: ; order with ascending values clr.l d0 move.w nslots,d0 jsr flib[random] cmpi.b #-1,0(a0,d0.w) ;if slot is occupied try again bne rand_num move.b d1,0(a0,d0.w) ;store current tile's value (loop value+1) addi.b #1,0(a0,d0.w) ; in the slot dbf.w d1,rand_num clr.b made_move ;indicate that no moves have been made yet ; *******************Did You Win?******************** game_loop: lea slots,a0 ;check for monotonically increasing values move.w nslots,d5 ; row by row subi.w #2,d5 move.w d5,d0 cmpi.b #0,1(a0,d0.w) ;if the last slot has the space (0) don't check dbne d0,spcl_chk ; it because although its position is valid, it spcl_chk: ; is not in monotonically increasing order cmp.b 1(a0,d0.w),d5 dbf.w d0,win_chk subi.w #1,d5 cmp.b 1(a0,d0.w),d5 dbf.w d0,win_chk bra cont_game win_chk: move.b 1(a0,d0.w),d1 cmp.b 0(a0,d0.w),d1 blt cont_game ;if didn't win row by row, check for win in dbf.w d0,win_chk ; the column by column configuration win: tst.b made_move ;if winning configuration without having made beq start_game ; a move, generate a new configuration jsr flib[clr_scr] ;else, valid win WriteStr #58,#30,#4,congrat WriteStr #90,#50,#4,winner SetFont #1 WriteStr #95,#70,#4,moves move.w #135,d3 move.w #70,d4 move.w count,d5 move.w #4,d6 bsr write_tile jsr flib[idle_loop] move.w #0,count jsr flib[clr_scr] SetFont #2 WriteStr #75,#30,#4,again SetFont #1 WriteStr #85,#50,#4,again1 WriteStr #85,#60,#4,again2 loop_again: jsr flib[idle_loop] IfKey #268,main_menu IfKey #269,end_game jmp loop_again cont_game: tst.b made_move ;bypass drawing the board if a move has bne draw_cursor ; already been made move.b #1,made_move ;indicate that moves will be made SetFont #2 lea slots,a0 ;draw the board before allowing first move clr.l d5 move.b nrows,d5 subi.b #1,d5 move.w d5,d0 row_loop: move.w d0,d4 mulu.w #ROWHGT,d4 addi.l #ROWSTRT,d4 ;d4=y coordinate of current tile clr.l d5 move.b ncols,d5 subi.b #1,d5 move.w d5,d1 col_loop: move.l d1,d3 mulu.w #COLWTH,d3 addi.l #COLSTRT,d3 ;d3=x coordinate of current tile move.w d0,d5 clr.l d6 move.b ncols,d6 mulu d6,d5 add.l d1,d5 move.b 0(a0,d5.l),d5 ;d5=current tile's value move.w #4,d6 ;d6=black on white bsr write_tile ;display the current tile dbf.w d1,col_loop dbf.w d0,row_loop move.w xspace,xcur ;initialize cursor over the space move.w yspace,ycur move.w spslotofs,curslotofs draw_cursor: move.w xcur,d3 ;draw the cursor (reverse background) over mulu.w #COLWTH,d3 ; the current tile addi.l #COLSTRT,d3 ;d3=x coordinate of current tile move.w ycur,d4 mulu.w #ROWHGT,d4 addi.l #ROWSTRT,d4 ;d4=y coordinate of current tile move.w curslotofs,d5 move.b 0(a0,d5),d5 ;d5=value of current tile move.w #0,d6 ;d6=reverse background bsr write_tile ;draw cursor (display current tile in reverse ; background) clr.w d1 ;permit the cursor to be moved and then clr.w d2 ; determine its new position loop_curs: ; NOTE: the cursor can be moved up, down, and jsr flib[idle_loop] ; diagonally and cursor wraparound is IfKey #338,north ; supported IfKey #342,northeast IfKey #340,east IfKey #348,southeast IfKey #344,south IfKey #345,southwest IfKey #337,west IfKey #339,northwest IfKey #268,which_tile ;if F1 key were pressed tile move is requested IfKey #'q',main_menu ;'q' key stops the game jmp loop_curs northeast: ;set d1 and d2 to the direction the cursor move.w #1,d1 ; was moved as follows: north: ; d1=-1, left; d1=+1, right move.w #-1,d2 ; d2=-1, up; d2=+1, down bra calc_coords southeast: move.w #1,d2 east: move.w #1,d1 bra calc_coords southwest: move.w #-1,d1 south: move.w #1,d2 bra calc_coords northwest: move.w #-1,d2 west: move.w #-1,d1 calc_coords: ;calculate the row and column of the new add.w xcur,d1 ; cursor position (d1=column, d2=row) bmi xmax clr.l d5 move.b ncols,d5 subi.b #1,d5 cmp.w d5,d1 ble chk_y clr.w d1 bra chk_y xmax: clr.l d5 move.b ncols,d5 subi.b #1,d5 move.w d5,d1 chk_y: add.w ycur,d2 bmi ymax clr.l d5 move.b nrows,d5 subi.b #1,d5 cmp.w d5,d2 ble erase_curs clr.w d2 bra erase_curs ymax: clr.l d5 move.b nrows,d5 subi.b #1,d5 move.w d5,d2 erase_curs: move.w d1,xcur ;remember new row and column for where cursor move.w d2,ycur ; is to be drawn move.w curslotofs,d5 move.b 0(a0,d5),d5 ;d5=value of current tile move.w #4,d6 jsr write_tile ;restore tile box where cursor was move.w ycur,d0 ;compute the offset into the slots vector for clr.l d5 move.b ncols,d5 mulu d5,d0 ; the new cursor position add.w xcur,d0 move.w d0,curslotofs ;save offset of tile covered by cursor lea slots,a0 ;restore the pointer to the slots vector bra draw_cursor which_tile: ;determine if the tile under the cursor can move.w ycur,d0 ; be moved sub.w yspace,d0 ;legal moves are limited to tiles that are cmpi.w #-1,d0 ; immediately adjacent to the space beq testcol cmpi.w #1,d0 bne trycols testcol: move.w xcur,d0 cmp.w xspace,d0 beq valid_move trycols: move.w xcur,d0 sub.w xspace,d0 cmpi.w #-1,d0 beq testrow cmpi.w #1,d0 bne invalid_move testrow: move.w ycur,d0 cmp.w yspace,d0 beq valid_move invalid_move: ;an invalid move was attempted player bra loop_curs ; must reposition the cursor and try again valid_move: ;a valid move was requested, so swap the addi.w #1,count lea slots,a0 ; current tile and the space and display the move.w curslotofs,d3 ; cursor over the space move.w spslotofs,d4 move.b 0(a0,d3.w),0(a0,d4.w) move.b 0(a0,d4.w),d5 ;d5=moved tile's value move.b #0,0(a0,d3.w) move.w d3,spslotofs move.w xspace,d3 move.w yspace,d4 move.w xcur,xspace move.w ycur,yspace mulu.w #COLWTH,d3 addi.l #COLSTRT,d3 mulu.w #ROWHGT,d4 addi.l #ROWSTRT,d4 move.w #4,d6 jsr write_tile ;display tile in its new position bra game_loop ;branch back to check for win end_game: jsr flib[clr_scr] ;clear screen rts ;write_tile: subroutine to write a tile's value in a specified slot ; Arguments: ; d3 = x coordinate of slot ; d4 = y coordinate of slot ; d5 = tile value ; d6 = 'color' value ; Return: nothing write_tile: movem.l d0-d2/a0,-(a7) ;save regs in preparation for romlib calls cmpi.b #0,d5 ;check for space bne not_space move.w #$2020,buffer ;store spaces in buffer bra write_buffer not_space: andi.w #$00FF,d5 ;clear out ms byte of the lower half of d4 move.w d5,-(a7) ;put arguments for sprintf onto the stack pea format(PC) pea buffer(PC) jsr romlib[sprintf] lea 10(a7),a7 ;discard arguments from stack write_buffer: WriteStr d3,d4,d6,buffer ;draw the current tile movem.l (a7)+,d0-d2/a0 rts ; ******************* "variables" ******************** curslotofs dc.w 0 ;offset into slots vector of tile covered by the cursor spslotofs dc.w 0 ;offset into slots vector for the space xcur dc.w 0 ;the x (col) position for cursor ycur dc.w 0 ;the y (row) position for cursor xspace dc.w 0 ;the x (col) position for the space yspace dc.w 0 ;the y (row) position for the space buffer dc.b " ",0 ;buffer for sprintf function ;Note: must be aligned to a word boundary format dc.b "%2d",0 prog_name dc.b "Tile Slider v1.0",0 ;name which will appear on Fargo menu author dc.b "By Dave Jaklitsch ",0 copy dc.b 169," 1997 D. JacKaL Software",0 press dc.b "Press any key to begin",0 new dc.b "[F1] - Start Game",0 help dc.b "[F2] - Help",0 about dc.b "[F3] - About",0 quit dc.b "[Q] - Quit",0 help1 dc.b "Here are the key functions:",0 help2 dc.b "Arrow keys move cursor",0 help3 dc.b "F1 slides tile",0 help4 dc.b "Q quits the game",0 help5 dc.b "See the doc for more info",0 about1 dc.b "v1.0 released on 7/16/97",0 congrat dc.b "Congratulations!",0 winner dc.b "You Won!",0 moves dc.b "Moves:",0 again dc.b "Play Again?",0 again1 dc.b "[F1] - Yes",0 again2 dc.b "[F2] - No",0 numcols dc.b "F1 < # of columns = > F5",0 numrows dc.b "F2 < # of rows = > F6",0 enter dc.b "[ENTER] - Begin Game",0 quit2 dc.b "[Q] - Main Menu",0 ncols dc.b 3 nrows dc.b 3 nslots dc.w 0 slots ds.b MAXSLTS+1 made_move dc.b 0 ;flag to indicate at least one move was made count dc.w 0 ;counts # of moves made ;************** End of Fargo program **************** reloc_open add_library flib add_library romlib add_library hexlib reloc_close end