Console Games
We wondered how easy it would be to program simple console games using MASM. This would require changing the colours of the text and background and would need equivalents of Pascal crt routines such as GoToXY. We decided to convert the first version of Joe's SnakeWithoutATail to MASM assembler. The code of snake.asm is below. It runs with this script in a batch file in the same directory as snake.asm on the same drive as MASM:
\masm32\bin\ml /c /Zd /coff snake.asm \masm32\bin\Link /SUBSYSTEM:CONSOLE snake.obj snake
The locate procedure is the equivalent of GoToXY, except that the parameters X and Y are zero-based. Similar to Pascal's random function, nrandom when passed a parameter Num returns (in the EAX register) a random integer in the range 0 to Num - 1. The random seed has the identifier nrandom_seed. You could ask the user to input a value for the random seed or use one based on time, perhaps by using the GetLocalDateTime procedure.
We changed the colours using SetConsoleTextAttribute, but were surprised that ClearScreen did not use our supplied argument for the text and background colours. Instead, we printed a string comprising 2000 spaces!
;SnakeWithoutATail Version 1.0 ;Pascal version copyright (c) 2012 Joe ;Licensed under the Apache License, Version 2.0 (the "License"); you may ;not use this file except in compliance with the License, as described at ;http://www.apache.org/licenses/ and http://www.pp4s.co.uk/licenses/ include \masm32\include\masm32rt.inc .686 .data nrandom_seed DD 12345678 ;Change this for variety spaces db 2000 dup(32),0 X DD 10 Y DD 10 FoodX DD ? FoodY DD ? hOutPut DWORD ? CCI CONSOLE_CURSOR_INFO {} OldK DD ? K DD ? Speed DD 120 SlowSpeed DD 120 FastSpeed DD 60 .code START: invoke GetStdHandle, STD_OUTPUT_HANDLE MOV hOutPut, EAX ;Turn off the cursor invoke GetConsoleCursorInfo, hOutPut, ADDR CCI MOV CCI.bVisible, 0 invoke SetConsoleCursorInfo, hOutPut, ADDR CCI invoke SetConsoleTextAttribute, hOutPut, FOREGROUND_BLUE OR BACKGROUND_GREEN ;Clear screen to green. invoke locate, 0, 0 print OFFSET spaces SetConsoleCaption "Snake without a tail" invoke locate, 0, 0 print "Welcome To The Game",13,10 ;This is the start screen. print "Instructions",13,10 print "Eat fruit",13,10 print "W - Up",13,10 print "S - Down",13,10 print "D - Right",13,10 print "A - Left",13,10 print "Space - toggle run or walk",13,10 print "ESC - End",13,10 print "Press any key to begin",13,10 getkey cls CALL PrintFood invoke locate, X, Y print "#" StartLoop: call crt__kbhit ;EAX is zero if no key press Test EAX, EAX JZ Move ;jump to Move if EAX is zero MOV EAX, K MOV OldK, EAX ; store old key call crt__getch ; get new key MOV K, EAX Move: CMP K, 119 ; 'w' JE Up CMP K, 97 ; 'a' JE Left CMP K, 115 ; 's' JE Down CMP K, 100 ; 'd' JE Right CMP K, 32 ;space toggles speed JNE CheckEscape MOV EAX, Speed CMP EAX, SlowSpeed JE @F ;Jump forward to @@ MOV EAX, SlowSpeed MOV Speed, EAX JMP SameDirection @@: MOV EAX, FastSpeed MOV Speed, EAX JMP SameDirection CheckEscape: CMP K, 27 JNE SameDirection exit SameDirection: MOV EAX, OldK ;Use the previous key MOV K, EAX JMP StartLoop Right: invoke locate, X, Y print " " INC(X) CMP X, 79 JLE PrintPlayer MOV X, 0 JMP PrintPlayer Left: invoke locate, X, Y print " " DEC(X) CMP X, 0 JGE PrintPlayer MOV X, 79 JMP PrintPlayer Up: invoke locate, X, Y print " " DEC(Y) CMP Y, 0 JGE PrintPlayer MOV Y, 24 JMP PrintPlayer Down: invoke locate, X, Y print " " INC(Y) CMP Y, 24 JLE PrintPlayer MOV Y, 0 PrintPlayer: MOV EAX, X CMP EAX, FoodX JNE PrintIt MOV EAX, Y CMP EAX, FoodY JNE PrintIt CALL PrintFood PrintIt: invoke locate, X, Y print "#" invoke Sleep, Speed JMP StartLoop RET PrintFood: invoke nrandom, 25 MOV FoodY, EAX invoke nrandom, 80 MOV FoodX, EAX invoke locate, FoodX, FoodY print "&" RET CALL START END START
We developed and tested this code as a preliminary to adapting Jack Crenshaw's TINY compiler to translate crt-type TINY statements; TINY14_CRT generates similar MASM assembler code. We then converted Joe's SnakeWithoutATail from Pascal to TINY and used it to test the new functionality in the compiler.