TITLE "MP5, Life, by Douglas Jones" ; Dec 1, 2011 USE "hawk.h" USE "monitor.h" INT MAIN ; Main program - main loop of the game board editor ; activation record of main program ARSIZE = 4 MAIN: ; expects R3 = width ; R4 = height ; uses R8 = xcursor -- constrained to be odd ; R9 = ycursor ; R10 = xmax -- constrained to be odd ; R11 = ymax ; R12 = command character STORES R1,R2 LIS R5 ,-2 ADDSI R3,-1 AND R3,R5 ADDSI R3,-1 MOVE R10,R3 ; xmax = ((width-1)&-2)-1 ADDSI R4,-1 MOVE R11,R4 ; ymax = (height-1) SR R3,1 AND R3,R5 ADDSI R3,1 MOVE R8,R3 ; xcursor = ((xmax/2)&-2)+1 SR R4,1 MOVE R9,R4 ; ycursor = ymax/2 MAINLP: ; do (;;) { ADDI R2,R2,ARSIZE ; -- begin block of I/O calls ADDI R3,R8,-1 ; -- first plot cursor MOVE R4,R9 LIL R1,PUTAT JSRS R1,R1 ; at(xcursor-1,ycursor) LIS R3,'(' LIL R1,PUTCHAR JSRS R1,R1 ; putchar('(') ADDI R3,R8,+1 MOVE R4,R9 LIL R1,PUTAT JSRS R1,R1 ; at(xcursor+1,ycursor) LIS R3,')' LIL R1,PUTCHAR JSRS R1,R1 ; putchar(')') LIL R1,GETCHAR ; -- then wait for keypress JSRS R1,R1 ; ch = getchar; MOVE R12,R3 ; -- move ch to safety ADDI R3,R8,-1 ; -- and then unplot cursor MOVE R4,R9 LIL R1,PUTAT JSRS R1,R1 ; at(xcursor-1,ycursor) LIS R3,' ' LIL R1,PUTCHAR JSRS R1,R1 ; putchar(' ') ADDI R3,R8,+1 MOVE R4,R9 LIL R1,PUTAT JSRS R1,R1 ; at(xcursor+1,ycursor) LIS R3,' ' LIL R1,PUTCHAR JSRS R1,R1 ; putchar(' ') ADDI R2,R2,-ARSIZE ; -- end block of I/O calls CMPI R12,' ' BLT MAINIG CMPI R12,'~' BGT MAINIG ; if (ch >= ' ') || (ch <= '~') { ADDI R12,R12,-' ' ; -- bias by first jump table entry LEA R1,JUMPTAB ADDSL R12,R1,2 LOADS R12,R12 JUMPS R12 ; select (ch) { MAINQ: ; case 'q','Q': LOADS R1,R2 JUMPS R1 ; return MAINS: ; case 's','S': ADDI R2,R2,ARSIZE JSR R1,LIFESTEP ; lifestep() ADDI R2,R2,-ARSIZE BR MAINIG ; break MAINH: ; case 'h','H': ADDSI R8,-2 ; xcursor = xcursor - 2 BR MAINIG ; break MAINY: ; case 'y','Y': ADDSI R8,-2 ; xcursor = xcursor - 2 ADDSI R9,-1 ; ycursor = ycursor - 1 BR MAINIG ; break MAINU: ; case 'u','U': ADDSI R9,-1 ; ycursor = ycursor - 1 BR MAINIG ; break MAINI: ; case 'i','I': ADDSI R8,2 ; xcursor = xcursor + 2 ADDSI R9,-1 ; ycursor = ycursor - 1 BR MAINIG ; break MAINK: ; case 'k','K': ADDSI R8,2 ; xcursor = xcursor + 2 BR MAINIG ; break MAINC: ; case ',','<': ADDSI R8,2 ; xcursor = xcursor + 2 ADDSI R9,1 ; ycursor = ycursor + 1 BR MAINIG ; break MAINM: ; case 'm','M': ADDSI R9,1 ; ycursor = ycursor + 1 BR MAINIG ; break MAINN: ; case 'n','N': ADDSI R8,-2 ; xcursor = xcursor - 2 ADDSI R9,1 ; ycursor = ycursor + 1 BR MAINIG ; break MAINJ: ; case 'j','J': MOVE R3,R8 MOVE R4,R9 ADDI R2,R2,ARSIZE JSR R1,TOGGLE ; toggle(xcursor,ycursor) ADDI R2,R2,-ARSIZE BR MAINIG ; break MAINIG: ; } ; -- do range checks to force edge rules CMPI R8,1 BGE MAINRL ; if (xcursor < 1) { LIS R8,1 ; xcursor = 1 MAINRL: ; } CMP R8,R10 BLE MAINRR ; if (xcursor > xmax) { MOVE R8,R10 ; xcursor = xmax MAINRR: ; } TESTR R9 BGE MAINRU ; if (ycursor < 0) { LIS R9,0 ; ycursor = 0 MAINRU: ; } CMP R9,R11 BLE MAINRD ; if (ycursor > ymax) { MOVE R9,R11 ; ycursor = ymax MAINRD: ; } BR MAINLP ; } ALIGN 4 ; Jump table, one entry per ASCII character, SP to '~' JUMPTAB: ; SP ! " # $ % & ' W MAINIG,MAINIG,MAINIG,MAINIG,MAINIG,MAINIG,MAINIG,MAINIG ; ( ) * + -,- - . / W MAINIG,MAINIG,MAINIG,MAINIG,MAINC ,MAINIG,MAINIG,MAINIG ; 0 1 2 3 4 5 6 7 W MAINIG,MAINIG,MAINIG,MAINIG,MAINIG,MAINIG,MAINIG,MAINIG ; 8 9 : ; -<- = > ? W MAINIG,MAINIG,MAINIG,MAINIG,MAINC ,MAINIG,MAINIG,MAINIG ; @ A B C D E F G W MAINIG,MAINIG,MAINIG,MAINIG,MAINIG,MAINIG,MAINIG,MAINIG ;-H- -I- -J- -K- L -M- -N- O W MAINH ,MAINI ,MAINJ ,MAINK ,MAINIG,MAINM ,MAINN ,MAINIG ; P -Q- R -S- T -U- V W W MAINIG,MAINQ ,MAINIG,MAINS ,MAINIG,MAINU ,MAINIG,MAINIG ; X -Y- Z [ \ ] ^ _ W MAINIG,MAINY ,MAINIG,MAINIG,MAINIG,MAINIG,MAINIG,MAINIG ; ` a b c d e f g W MAINIG,MAINIG,MAINIG,MAINIG,MAINIG,MAINIG,MAINIG,MAINIG ;-h- -i- -j- -k- l -m- -n- o W MAINH ,MAINI ,MAINJ ,MAINK ,MAINIG,MAINM ,MAINN ,MAINIG ; p -q- r -s- t -u- v w W MAINIG,MAINQ ,MAINIG,MAINS ,MAINIG,MAINU ,MAINIG,MAINIG ; x -y- z { | } ~ W MAINIG,MAINY ,MAINIG,MAINIG,MAINIG,MAINIG,MAINIG SUBTITLE "toggle(x,y) -- toggle cell on screen" ; access to memory mapped display interface DISPBASE = #FF000000 DISPLINES = 0 DISPCOLS = 4 DISPTEXT = #100 ; activation record format ;RETAD = 0 SAVEX = 4 ARSIZE = 8 TOGGLE: ; expects R3 = x coordinate ; expects R4 = y coordinate ; toggles character at x,y between blank and * STORES R1,R2 STORE R3,R2,SAVEX ; -- set aside X coord LIW R3,DISPBASE+DISPCOLS LOADS R5,R3 ; -- parameters are R4=y and R5=dispcols ADDI R2,R2,ARSIZE LIL R1,TIMES JSRS R1,R1 ; R3 = times( dispcols, y ) ADDI R2,R2,-ARSIZE LOAD R4,R2,SAVEX ADD R3,R3,R4 ; R3 = x + times( dispcols, y ) LIW R5,DISPBASE+DISPTEXT ADD R3,R3,R5 ; R3 = &(disptext[x,y]) LOADS R4,R3 EXTB R5,R4,R3 ; R5 = disptext[x,y] LIS R6,'*'-' ' EQU R5,R6 NOT R5 ; R5 = R5 xor ('*'-' ') -- toggles character STUFFB R4,R5,R3 STORES R4,R3 ; disptext[x,y] = R5 LOADS R1,R2 JUMPS R1 ; return SUBTITLE "lifestep() -- run one generation of life" ; access to memory mapped display interface DISPBASE = #FF000000 DISPLINES = 0 DISPCOLS = 4 DISPTEXT = #100 ; activation record format ;RETAD = 0 R8SV = 4 R9SV = 8 ARSIZE = 12 ; Neighborhood planning during each iterative walk over the screen ; ; -w-2 -w -w+2 r is the number of cells per row, in R ; -2 ** +2 <- address of cell ** is in R ; +w-2 +r +w+2 ; LIFESTEP: ; no parameters, no return value ; advances screen one step in the game of life STORES R1,R2 STORE R8,R2,R8SV STORE R9,R2,R9SV LIW R3,DISPBASE LOAD R4,R3,DISPLINES ; h -- lines on screen (outer loop index) LOAD R5,R3,DISPCOLS ; w -- columns on screen LEA R6,R3,DISPTEXT ; p -- pointer to spot ; -- first cell is down one, over 3 ADD R6,R6,R5 ; -- allows for margin around cells in play ADDSI R6,3 ; p = p + w + 3 ADDSI R4,-2 ; h = h - 2 -- 2 lines used up by margin LIFEOL1: ; for (;;) { ADDSI R4,-1 ; h = h - 1 -- count off one line BLT LIFEOQ1 ; if (h < 0) break ADD R7,R6,R5 ; np = p + w -- first cell on next line ADDI R8,R7,-6 ; lp = np - 6 -- last cell on this line ; -- the above allows 2 margins LIFEIL1: ; for (;;) { CMP R6,R8 BGEU LIFEIQ1 ; if (p >= lp) break ; -- work on cell at p LOADS R1,R6 EXTB R3,R1,R6 ; ch = *p LIS R9,'*'-' ' ; -- this is stupid, just a test, works EQU R3,R9 NOT R3 ; ch = ch xor ('*'-' ') -- toggles STUFFB R1,R3,R6 ; *p = ch STORES R1,R6 ; -- end of work on cell at p ADDSI R6,2 ; p = p + 2 -- advance to next cell BR LIFEIL1 LIFEIQ1: ; } MOVE R6,R7 ; p = np BR LIFEOL1 LIFEOQ1: ; } LOAD R8,R2,R8SV LOAD R9,R2,R9SV LOADS R1,R2 JUMPS R1 ; return END