;-------------------------------------------------------------------- ; Player Movement Demo - NTSC - Puts a character on the 16x16 grid and ; you can move it with the arrows ; ; Victor Elci ; Jonathan Eren ;-------------------------------------------------------------------- ;Setup Device DEVICE SX28L, STACKX, CARRYX, OPTIONX, TURBO, OSCHS3, IFBD IRC_CAL IRC_SLOW RESET Start FREQ 80_000_000 ;----------------------------------------------------------------------- ;constants ;----------------------------------------------------------------------- CLK_SCALE equ (8) ; used to make calling the DELAY macro easier ; set this to the frequency / 10,000,000 SYNC equ (0) ; Sync pulse - 0v ;BLACK equ (4) ; Color Black - roughly .3v ;WHITE equ (15) ; Color White - 1v ;variables for outputting through sound port BLACK equ (128) ; Color Black - roughly .3v (Output through sound port) WHITE equ (224) ; Color White - 1v (Output through sound port) ;------------------------------------------------------------------------ ;variables ;------------------------------------------------------------------------ org $08 counter ds 1 ; general counter (used in delay) counter2 ds 1 ; general counter (used in delay) ScanLine ds 1 ; the current scanline counter CurrentPixel ds 1 ; Row of character graphic with pixel data XPixels ds 1 ; Counter for moving along X axis pixels CharRow ds 1 ; counter for rows for a character graphic CurrentChar ds 1 ; current character in memory(not yet used) PlayerX ds 1 ; x position of the player PlayerY ds 1 ; y position of the player GridX ds 1 ; counter for current x position of the grid GridY ds 1 ; counter for current y position of the grid CharCol ds 1 ; counter for which character column is current PlayerRow ds 1 ; next row to be drawn of the player RobotRow ds 1 ; next row to be drawn of the robot BoolRow ds 1 ; keeps track of what is on which row ButtonFlag ds 1 ; keeps track of previous button presses ; **** MACROS ***************************************************************** ; ***************************************************************************** ; * ; * DELAY ; * ; * Delays for microseconds. DELAY MACRO clocks ; this macro can handle large delays up to 25,500 cycles, so to call it use the following ; constructions ; cycle delay ; DELAY(number_of_clocks) ; for 80 mhz clock, microsecond parameters ; DELAY(80*microseconds) ; example you want a 4.5 uS delay ; 80*4.5 = 360 ; DELAY(360) ; the preprocessor can NOT do floating point math, so another construction would be to scale ; all values by 10 then multiply by 8 rather than 80, for example, a 4.5 uS delay could be ; written ; DELAY(8*45) ; which is a little more intuitive ; first compute fractional remainder of 10 and delay IF (((clocks) // 10) > 0) ; first 3 clock chunks REPT (((clocks) // 10)/3) JMP $ + 1 ENDR ; now the remainder if any REPT (((clocks) // 10)//3) NOP ENDR ENDIF ; next multiples of 100 IF (((clocks) / 100) >= 1) ; delay 100*(clocks/100), loop equals 100, therefore 1*(clocks/100) iterations mov counter, #((clocks)/100) ; (2) :Loop mov counter2, #24 ; (2) :Loop100 djnz counter2, :Loop100 ; (4/2) djnz counter, :Loop ; (4/2) ENDIF ; last compute whole multiples of 10, and delay IF (( ((clocks) // 100) / 10) >= 1) ; delay 10*(clocks/10), loop equals 10, therefore (clocks/10) iterations mov counter, #( ((clocks) // 100) / 10) ; (2) :Loop2 jmp $ + 1 ; (3) jmp $ + 1 ; (3) djnz counter, :Loop2 ; (4/2) ENDIF ENDM ;----------------------------------------------------------------------- ;Start of program, setup ;------------------------------------------------------------------------ org $000 Start ;Configure port settings mov rc, #%00000000 ;Port C output zero mov !rc,#%00000000 ;Port C all output mov !RB, #%11111111 ; Set port B direction mov w, #$1E ; Set mode register to write pullup resistor mov m, w mov !RB, #%00000000 ; Set joystick inputs pullups on (0=on, 1=off) mov PlayerX, #8 mov PlayerY, #8 ;----------------------------------------------------------------------- ;New screen, starts at the top of the screen and work its way down NewScreen ; Total of 525 scanlines(divided by 2 is 262.5) ; Timing of a scanline ; 1.5us of black - front porch ; 4.7us of sync - hsync pulse ; 4.7us of black - back porch ; 52.6us of image data ; .06us of image data remaining that we will just pad ; 63.56us = a single scan line ;256 scanlines of video data mov ScanLine, #0 ;(2) set number of scanlines with video data ; NOTE: When this is subtracted, it will ; underflow to 255 giving us 256 scanlines mov CharRow, #255 ;(2) first row for character ; (this will overflow to zero) mov GridY, #0 ;(2) init y position HSync mov rc, #black ;(2) output black for front porch jmp SetupRow ;(3) Setup the row # for character ; also place current row of char in memory ;22 cycles were spent after returning from jump ;We will also init the the character row line here since we have enough time FinishRowInit DELAY (CLK_SCALE * 15 - 52) ; 1.5us of black - front porch mov rc, #SYNC ;(2) output sync signal DELAY (CLK_SCALE * 47 - 2) ; 4.7us of sync - hsync pulse mov rc, #black ; (2)output black for back porch DELAY (CLK_SCALE * 47 - 2) ; 4.7us of black - back porch ;Scanline start 52.66us ---------------------------------------------------------------- mov rc, #White ;(2) Pull out of back porch ReadNextCol: ;decide which sprite is drawn next CSNE GridX, PlayerX ; (3 or 4) SB BoolRow.0 ; (1 or 2) JMP SetBlank ; (3) SetPlayer: MOV CurrentPixel, PlayerRow ; (2) nop nop JMP DrawNextPixel ; (3) SetBlank: MOV CurrentPixel, #0; ; (2) JMP DrawNextPixel ; (3) ; 12 cycles for any path WaitNextPixel: ; 2 to sync end of drawnextpixel nop nop ; 12 to sync with readnextcol nop nop nop nop nop nop nop nop nop nop nop nop DrawNextPixel: ; checks bitmap, if 1, draw white pixel, else draw black pixel mov W, #Black ;(1) default to black pixel SNB CurrentPixel.7 ;(1,2)if the bit is zero, then skip white pixel mov W, #White ;(1) if bit is not zero, set to white pixel mov rc, W ;(1) move pixel color to video register rl CurrentPixel ;(1) shift all the bits over left one, ; 5 cycles inc CharCol ;(1) zero flag is cleared SB CharCol.3 ;(1,2) jmp EndInc ;(3) inc GridX ;(1) CLR CharCol ;(1) zero flag is set EndInc: ;5 cycles nop nop CSE CharCol, #0 ; (3,4) jmp WaitNextPixel ; (3) djnz XPixels, ReadNextCol; ;(2,4) 32 clocks total nop nop ; the extra 2 from not jumping are covered at the start when ; we pull out of the back porch delay(112) ; pad the the scanline for correct timing ; we still have .06uS of scanline image remaining, if we take ; .06 and multiply it by our clock cycle 80, we get 4.8, which we ; will round down to 4 clock cycles djnz ScanLine, HSync ; (2,4) run through all scan lines ;------------------------------------------------------------------------ ;Vertical sync pulse, 6 lines(totaling of 262) ;------------------------------------------------------------------------ mov ScanLine, #6 ; (2)set 6 sync scanlines, ; makes up for 2 from above VSync mov rc, #SYNC ; (2) send out sync signal ; add 4 more for djnz DELAY (CLK_SCALE * 635 - 6) ; delay for 63.5u djnz ScanLine, VSync ;(2,4) run through 6 scanlines jmp NewScreen ;(3) start the drawing processes over ;------------------------------------------------------------------------ ; Sets up the row number for the character - this is done during the front porch ;------------------------------------------------------------------------ SetupRow mov XPixels, #16 ; (2) Number of horizontal pixels mov GridX, #0 ; (2) initialize grid x direction counter to 0 SNB Scanline.0 ; (1,2) Don't increment CharRow if scanline is even inc CharRow ; (1) move down one row for char STC ; (1) set carrier bit so it will jump on compare ; 7 total CJNE CharRow,#8,DelayReadRow ;(4,6) if counter has hit 0 then do not ; jump so we can reset the row counter mov CharRow, #0 ;(2) reset row counter inc GridY ;(1) inc grid pos jmp ReadRow ;(3) jump to read row DelayReadRow nop nop nop nop ReadRow ; 7(from prev) + 10(from this) = 17 total cycles ; setup rows MOV M, #Player >> 8 ; (1) Store high nibble in M MOV W, #Player ; (1) Store low byte in W CLC ; (1) Clear carry bit ADD W, CharRow ; (1) Add the offset into the table IREAD ; (4) Get the value from table ; IREAD grabs the 12 byte address ; from both M and W MOV PlayerRow, W ; (1) move value of character into memory ; 17(from prev) + 9(from this) = 26 total cycles ; listen for buttons and move player SB RB.0 ; (1,2) test for UP jmp UP ; (3) SB RB.1 ; (1,2) test for DOWN jmp DOWN ; (3) SB RB.2 ; (1,2) test for LEFT jmp LEFT ; (3) SB RB.3 ; (1,2) test for RIGHT jmp RIGHT ; (3) SB RB.4 ; (1,2) test for FIRE jmp FIRE ; (3) nop ; (6) no operation for sync nop nop nop nop nop jmp NOBTN ; (3) jump back, 16 total cycles UP: SB ButtonFlag.0 ; (1,2) Skips inc if flag is set DEC PlayerY ; (1) Decrease player y position nop ; (6) no operation for sync nop nop nop nop nop SETB ButtonFlag.0 ; (1) sets flag that up button has been pressed jmp ENDPOLL ; (3) jump back, 16 total cycles DOWN: SB ButtonFlag.1 ; (1,2) Skips inc if flag is set INC PlayerY ; (1) Increase player y position nop ; (4) no operation for sync nop nop nop SETB ButtonFlag.1 ; (1) sets flag that down button has been pressed jmp ENDPOLL ; (3) jump back, 16 total cycles LEFT: SB ButtonFlag.2 ; (1,2) Skips inc if flag is set DEC PlayerX ; (1) Decrease player X position nop ; (2) no operation for sync nop SETB ButtonFlag.2 ; (1) sets flag that left button has been pressed jmp ENDPOLL ; (3) jump back, 16 total cycles RIGHT: SB ButtonFlag.3 ; (1,2) Skips inc if flag is set INC PlayerX ; (1) Increase player X position SETB ButtonFlag.3 ; (1) sets flag that right button has been pressed jmp ENDPOLL ; (3) jump back, 16 total cycles FIRE: ;DO NOTHING YET!!!! nop ; (1) no operation for sync jmp ENDPOLL ; (3) jump back, 16 total cycles NOBTN: CLR ButtonFlag ; (1) Clears flag for keeping track of buttons ENDPOLL: nop ; (2) nop for 2 cycles for sync purposes nop ; 19 cycles to receive input ; make sure input doesn't overload AND PlayerY, #%00001111 ; (2) restrict input to player y pos AND PlayerX, #%00001111 ; (2) restrict input to player x pos ; (4) cycles to restrict input ; set a flag (BoolRow.0) if playerY is equal to the gridY CLRB BoolRow.0 ; (1) CSNE GridY, PlayerY ; (2,4) SETB BoolRow.0 ; (1) ; (4,5)(cycles to set flag to determine player y position) jmp FinishRowInit ; (3) jump ;(52,53) total cycles ;------------------------------------------------------------------------ ; Character Table ;------------------------------------------------------------------------ ORG $200 Blank dw 0,0,0,0,0,0,0,0 ; blank Player dw 56,124,56,16,124,16,56,108 ; person Robot dw 124,84,124,16,124,16,124,68 ; robot (not used)