home *** CD-ROM | disk | FTP | other *** search
- ;KOLLUMS source for version 2.0
- ;
- ;Here is the source code for KOLLUMS v2.0
- ;I'm distributing it for all those people who want to learn assembly for the 86
- ;I've commented it very much, although I got kinda sick of commenting late at night :(
- ;
- ;
- ;Some of the stuff I added in v2.0 I didn't comment, too bad
- ;
- ;Please learn something from it, and if you do, give me some credit.
- ;
- ;mail me with anything!! --> bailela@charlie.cns.iit.edu
- ;
- ;This source is Copyright (C) 1997 Alan Bailey. Please don't redistribute any modified
- ;version of this program. You can modify all you want, just don't redistribute. Feel
- ;free to cut and paste something, but give me some credit. If you see anything wrong,
- ;or see something I could do better, mail me and tell me.
- ;
- ;If you want to recompile it, get Asm86 from ticalc.org at
- ;http://www.ticalc.org/pub/dos/asm/asm86.zip
- ;There's some stuff in here that's specific to that
- ;
- ;Alan Bailey
- ;bailela@charlie.cns.iit.edu
- ;http://www.iit.edu/~bailela/ <--- check my page out, it's new
- ;IRC: Abalone on #calc-ti on EFnet
-
-
- #include "asm86.h" ;I use Asm86 to compile, so I include this
- #include "ti86asm.inc" ;this is TI's include file
-
- .org _asm_exec_ram ;starting point for all asm progs, $D748
-
-
- ; XCoord ->
- ; ----------------
- ; |(0,0) (15,0)|
- ; | | Y 16*7=112 bytes
- ; | | C
- ; | | o
- ; | | o
- ; | | r
- ; |(0,7) (15,7)| d
- ; | info line | \/
- ; ----------------
-
- Start:
-
- call _clrLCD ;clear the screen!
- ld a,%01010101 ;this is the bitmap for the top seven lines of the intro
- ld b,7 ;we have seven lines
- ld hl,$FC00 ;this is the first spot we want to write to
- Graphxloop:
- push bc ;save the counter of lines
- ld b,16 ;make a new counter of bytes in the line (16)
- Graphxloop2:
- ld (hl),a ;put the bitmap in
- inc hl ;increment to the next byte on screen
- djnz Graphxloop2 ;and jump back until line is finished
- cpl ;this is equal to <xor 255>, to change the bitmap
- pop bc ;get the old counter back
- djnz Graphxloop ;and keep going until all seven lines done
- ;now we display some words
- ld bc,$0501 ;now we display the words, $0501 are first coordinates
- ld (_curRow),bc ;load them in, _curRow gets $01, _curCol gets $05
- ld hl,TitleStr ;this is absolute address of string "KOLLUMS 1.0"
- call _puts ;put it out on screen
- ld bc,$0303 ;next coordinates
- ld (_curRow),bc ;load them in
- ;ld hl,Author ;this string is right after the previous one, so hl set
- call _puts ;put it out
- ld bc,$220F
- ld (_penCol),bc
- ;ld hl,Email
- call _vputs ;this is a variable-width put string
- ld bc,$3103
- ld (_penCol),bc
- ;ld hl,Difficulty
- call _vputs
- call DispDiff ;this routine displays the boxes (difficulty)
- ld hl,ResumeStr
- ld bc,$3918
- ld (_penCol),bc
- call _vputs
- FirstKeyCheck:
- halt ;saves valuable battery power when waiting
- call Randomize ;Randomize the variables
- call GET_KEY ;gets the recent key pressed
- cp K_EXIT ;compare it to exit
- jr z,TimetoLeave ;if it's exit, go to TimetoLeave
- cp K_RIGHT ;and similar
- jp z,MoveLevelRight
- cp K_LEFT
- jp z,MoveLevelLeft
- cp K_ENTER
- jp z,StartAction
- cp K_SECOND
- jp z,StartAction
- cp K_F1
- jp z,ResumePaused
- jr FirstKeyCheck ;goes back to check other keys
-
- TimetoLeave:
- call LoadData
- call _clrLCD ;and clear the screen one last time
- ret ;and leave now that the scores are saved
-
- ResumePaused:
- ld a,(SavedGame)
- or a
- jp z,FirstKeyCheck ;no saved game
- call _clrLCD
- call PutScreen ;Puts out any blocks in the BlockMem
- ld hl,$3803 ;coords for LevelDiff
- ld (_penCol),hl ;loads them
- ld a,(LevelDiff) ;gets LevelDiff
- add a,'0' ;add '0' to make it ASCII char
- ld b,1 ;number of chars to display
- ld hl,StringPlace ;place to store char to display
- ld (hl),a ;puts it in
- call _vputsn ;displays 1 char pointed to by hl
- call UpdateScore ;Puts score
- call UpdateLevel ;Puts level
- call DispHigh ;Puts high score
- call DrawCurrent ;and Draws the current three blocks
- jp keycheck
-
-
- ;-----------------------------------
- ;This routine moves the difficulty level to the right
- ;from the intro screen, jumps back to FirstKeyCheck
- MoveLevelRight:
- ld a,(LevelDiff) ;gets the LevelDifficulty
- cp 8 ;the highest it can be
- jp z,FirstKeyCheck ;if it's the highest, go back now
- inc a ;or increment it!
- ld (LevelDiff),a ;loads it back
- ld a,1 ;the randoms might be upset by switching the difficulty
- ld (Rand1),a ;so this restarts all randoms
- ld (Rand2),a
- ld (Rand3),a
- call DispDiff ;and display the difficulty boxes again
- jp FirstKeyCheck ;jump back to key check
-
- ;-----------------------------------
- ;This routine moves the difficulty level to the left
- ;from the intro screen, jumps back to FirstKeyCheck
- MoveLevelLeft: ;this just like MoveLevelRight
- ld a,(LevelDiff)
- cp 3 ;the lowest point
- jp z,FirstKeyCheck
- dec a
- ld (LevelDiff),a
- ld a,1
- ld (Rand1),a
- ld (Rand2),a
- ld (Rand3),a
- call DispDiff
- jp FirstKeyCheck
-
-
- ;-----------------------------------
- ;This routine displays the boxes to represent
- ;the difficulty. Returns when it is done
- DispDiff:
- ld a,(LevelDiff) ;gets the LevelDifficulty = number of boxes
- ld b,a ;put in b as a counter
- ld a,$01 ;this is the first block bitmap we want to display
- ld de,$0706 ;xy position for first block
- DispDiff2:
- push bc ;saves bc (counter)
- push af ;saves af (block description)
- push de ;saves de (xy coords)
- push de ;no doens't save de, puts de in bc
- pop bc ;cause we pushed it, now it's popped into a differnet rp
- call DrawBlock ;and call DrawBlock with a containing block, bc has coords
- pop de ;gets the saved coords
- inc d ;and increment the xcoord
- pop af ;gets the saved block type
- inc a ;and moves to the next block
- pop bc ;gets the saved counter
- djnz DispDiff2 ;and does all blocks equal to LevelDiff
- ld a,$00 ;these next four lines put a blank block at the end
- push de ;just in case
- pop bc
- call DrawBlock
- ret ;and go back where you came from
-
-
- ;---------------------------
- ;This part called when all done selecting level
- ;and enter or second has been pressed
- StartAction:
- sub a ;make a zero, literally subtract a from a
- ld (SpeedLevel),a ;SpeedLevel is now zero
- ld hl,BlockMem
- ld de,BlockMem+1
- ld (hl),0
- ld bc,111
- ldir
- ld hl,$0660 ;This is the first DelayTimer value
- ld (DelayTimer),hl ;load it in to variable
- ld hl,$0000
- ld (Score),hl
-
- call _clrLCD
- call MakeNewSet ;make new set of three blocks
- call PutScreen ;Puts out any blocks in the BlockMem
- ld hl,$3803 ;coords for LevelDiff
- ld (_penCol),hl ;loads them
- ld a,(LevelDiff) ;gets LevelDiff
- add a,'0' ;add '0' to make it ASCII char
- ld b,1 ;number of chars to display
- ld hl,StringPlace ;place to store char to display
- ld (hl),a ;puts it in
- call _vputsn ;displays 1 char pointed to by hl
- call UpdateScore ;Puts score
- call UpdateLevel ;Puts level
- call DispHigh ;Puts high score
- call DrawCurrent ;and Draws the current three blocks
- keycheck:
- call Randomize ;called at random time to make it random
- call GET_KEY ;same kind of keyloop
- cp K_UP
- jp z,MoveLeft
- cp K_DOWN
- jp z,MoveRight
- cp K_SECOND
- jp z,RotateBlocks
- cp K_EXIT
- jp z,GameAllDone
- cp K_MORE
- jp z,PauseGame
- cp K_F1
- jr z,SuspendGame
- cp K_LEFT
- call z,MoveDown ;this is a call because MoveDown is a function
- ;will return here, no problem
- ld hl,(DelayTimer) ;gets the time delayed
- dec hl ;decrements it
- ld (DelayTimer),hl ;and load it back
- ld a,l ;puts l into a
- or h ;ors h with l, if _anything_ is set, it will not be zero
- jr nz,keycheck ;so if not zero, jr keycheck
-
- call MoveDown ;Time all decremented, move it down a notch
- ld a,(CurrFinished) ;CurrFinished is changed in MoveDown
- or a
- jp nz,FinishedSet ;if it is not zero, means finished, and goes to FinishedSet
- ld a,(SpeedLevel) ;these next eight lines make DelayTimer from SpeedLevel
- rlca ;rotate left, so number is multiplied by 2
- ld c,a ;puts that offset into bc
- ld b,0 ;like that
- ld hl,TimerTable ;now here's the table we want to analyze
- add hl,bc ;include the offset
- call LD_HL_MHL ;and get the value pointed to by hl in TimerTable
- ld (DelayTimer),hl ;that's the current DelayTimer
- jr keycheck ;and jump back to check the keys
-
-
- SuspendGame:
- ld a,1
- ld (SavedGame),a
- call LoadData
- call _clrLCD
- ret
-
-
-
- ;-------------------------
- ;Simple routine to follow when MORE is pressed
- PauseGame: ;
- halt ;saves some time and battery power
- call GET_KEY ;gets key
- cp 0 ;if anything,
- jp nz,keycheck ;go back to keycheck
- jr PauseGame ;or stay in this loop
-
-
- ;-----------------------------------
- ;Routine to move the blocks around in their set
- RotateBlocks:
- ld hl,CurrTop ;address of the top block
- ld b,(hl) ;put in b temporarily
- inc hl ;go to the middle block
- ld a,(hl) ;put the middle block in a
- ld (hl),b ;and the top block in the middle block
- inc hl ;go to the lower block
- ld b,(hl) ;put the lower block in b
- ld (hl),a ;put the middle block in the lower block
- ld hl,CurrTop ;get top block again
- ld (hl),b ;and put lower block in top block
- call DrawCurrent ;redraw it
- jp keycheck ;and jump back
-
-
-
- ;----------------------
- ;Routine to move the set to the left
- ;erases it and redraws it
- MoveLeft:
- ld hl,(YCoord) ;gets the y coord and x coord
- ld a,l ;puts y coord in a
- or a ;checks if zero, (at left side
- jp z,keycheck ;if at left side, go back now
- push hl ;puts hl
- pop bc ;in bc
- dec c ;dec y coord
- call GetBlock ;get value of block and address on left side of three
- inc hl ;next up block
- add a,(hl) ;get value
- inc hl ;next one
- add a,(hl) ;get value
- jp nz,keycheck ;basically, just check if any blocks to the left are occupied
-
- ld hl,(YCoord) ;gets block at bottome
- push hl ;puts hl
- pop bc ;in bc
- sub a ;makes it a blank block
- push bc ;saves coords for next run through
- call DrawBlock ;deltes block by putting blanks there
- pop bc ;gets saved coords
- inc b ;ready to erase next block
- sub a
- push bc
- call DrawBlock
- pop bc
- inc b
- sub a
- call DrawBlock ;all three blocks deleted
- ld hl,(YCoord) ;get coords
- dec l ;now we decrement it
- ld (YCoord),hl ;and load it back
- call DrawCurrent ;and draw it, how fun!
- jp keycheck ;and go back to checking keys
-
- MoveRight: ;just like MoveLeft, look above, it's very similar
- ld hl,(YCoord)
- ld a,l
- cp 6
- jp z,keycheck
- push hl
- pop bc
- inc c
- call GetBlock
- inc hl
- add a,(hl)
- inc hl
- add a,(hl)
- jp nz,keycheck
- ld hl,(YCoord)
- push hl
- pop bc
- sub a
- push bc
- call DrawBlock
- pop bc
- inc b
- sub a
- push bc
- call DrawBlock
- pop bc
- inc b
- sub a
- call DrawBlock
- ld hl,(YCoord)
- inc l
- ld (YCoord),hl
- call DrawCurrent
- jp keycheck
-
-
- ;-------------------
- ;This displays the high score for that level
- DispHigh:
- ld hl,$3810 ;place to put high score
- ld (_penCol),hl ;put it in
- ld hl,HighStr ;get string High:
- call _vputs ;put that little string
- ld a,(LevelDiff)
- cp 3
- jr z,DispHigh3 ;if level 3
- cp 4
- jr z,DispHigh4 ;if level 4
- cp 5
- jr z,DispHigh5 ;if level 5
- cp 6
- jr z,DispHigh6
- cp 7
- jr z,DispHigh7
- jr DispHigh8 ;defaults to level 8 if not anything else
-
- DispHigh3: ;gets address for High3
- ld hl,High3
- jr DispHigh2
- DispHigh4:
- ld hl,High4 ;gets address for High4
- jr DispHigh2
- DispHigh5:
- ld hl,High5
- jr DispHigh2
- DispHigh6:
- ld hl,High6
- jr DispHigh2
- DispHigh7:
- ld hl,High7
- jr DispHigh2
- DispHigh8:
- ld hl,High8
- jr DispHigh2
-
-
- DispHigh2: ;now it works on the information
- push hl
- call LD_HL_MHL ;gets the high score from mem
- ld de,StringPlace+4 ;sets de for putting score
- ld b,5 ;5 characters in score
- UpdateHigh:
- call UNPACK_HL ;divides hl by 10 and has the remainder in a,
- add a,'0' ;make digit ascii
- ld (de),a ;load it into stringplace, ready for displaying
- dec de ;next spot to load
- djnz UpdateHigh ;and go to UpdateHigh for next 4 characters
- ld hl,StringPlace ;now it contains the score, asciiized and zero-terminated
- call _vputs ;display the score
- ld a,(_penCol) ;get the Col from mem
- ld b,4 ;increase it
- add a,b ;like that
- ld (_penCol),a ;and load it back
- pop hl ;this is the address to high score
- inc hl ;right after it is Initials, so this increments to that
- inc hl
- call _vputs ;and put the Initials of High Scorer
- ret ;leave
-
-
- ;-----------------------
- ;randomizes the varialbes
- ;this is called many times from the keyloops
- ;This code is mostly (C) 1996 Mel Tsai from Columns3
- ;All commments are Mel Tsai's
-
- Randomize:
- ld a, (LevelDiff) ; this works on the fact
- inc a ; that the computer is so fast
- ld b, a ; that by the time you press a key
- ld a, (Rand1) ; to move, it can increment 3 variables
- inc a ; hundreds of times. These 3 variables
- cp b ; become the random blocks generated!
- jr z, RANDINC_1
- ld (Rand1), a
- ret
- RANDINC_1:
- ld a, 1
- ld (Rand1), a
- ld a, (Rand2)
- inc a
- cp b
- jr z, RANDINC_2
- ld (Rand2), a
- ret
- RANDINC_2:
- ld a, 1
- ld (Rand2), a
- ld a, (Rand3)
- inc a
- cp b
- jr z, RANDINC_3
- ld (Rand3), a
- ret
- RANDINC_3:
- ld a, 1
- ld (Rand3), a
- ret
-
-
-
-
- ;----------------------------------------------------------------
- ;----------------------------------------------------------------
- ;Huge routine to check all directions for rows of common blocks
- ;Runs through the Horizontal, then Vert, then the two diagonals
- ;----------------------------------------------------------------
- BlockTestTime:
- sub a
- ld (TotalBlockCount),a
-
- ;-----------
- Horiz:
- ld hl,BlockMem ;first spot of startingblock
- ld b,7 ;7 columns
- Horiz2:
- push bc ;save counter
- push hl ;save address of starting block
- ld e,16 ;16 in a line
- ld a,1 ;the difference between each block is one byte
- ld (BlockDiff),a ;like that
- call TestLine ;now we test that line, which tags them
- pop hl ;get address back
- ld de,$0010 ;add 16 to get to the next line
- add hl,de ;like that
- pop bc ;now we get the counter back for all seven
- djnz Horiz2
-
- ;-----------
- Vert:
- ld hl,BlockMem ;first spot of startingblock
- ld b,16 ;opposite of Horiz, so 16 columns
- Vert2:
- push bc ;save counter
- push hl
- ld e,7 ;number in line
- ld a,$0010 ;this is the difference now in the other direction
- ld (BlockDiff),a ;load it
- call TestLine ;Test that line
- pop hl ;get back startingblock
- inc hl ;go to next startingblock
- pop bc ;for all 16 times
- djnz Vert2 ;checked here
-
-
- ;-----------
- Diag1:
- ld hl,BlockMem ;starting position for diagonal
- ld b,10 ;10 diagonals of length 7
- Diag12:
- push bc ;save
- push hl ;save
- ld e,7 ;7 blocks in these 10 diagonals
- ld a,$0011 ;this means difference is one line ($10) + one block ($01)
- ld (BlockDiff),a ;load it into BlockDiff
- call TestLine ;and test
- pop hl
- inc hl ;inc to get to next starting block of diagonal
- pop bc
- djnz Diag12
- ;these next sets of three lines test the little diagonals
- ld hl,BlockMem+16 ;diagonal of length 6 starting at that block
- ld e,6
- call TestLine ;Test it! - BlockDiff is always the same
- ld hl,BlockMem+32
- ld e,5
- call TestLine
- ld hl,BlockMem+48
- ld e,4
- call TestLine
- ld hl,BlockMem+64
- ld e,3
- call TestLine
- ld hl,BlockMem+10
- ld e,6
- call TestLine
- ld hl,BlockMem+11
- ld e,5
- call TestLine
- ld hl,BlockMem+12
- ld e,4
- call TestLine
- ld hl,BlockMem+13
- ld e,3
- call TestLine
- ld hl,BlockMem+14
- call TestLine
-
- ;------------
- Diag2: ;refer to Diag1, this is very similar
- ld hl,BlockMem+6
- ld b,10
- Diag22:
- push bc
- push hl
- ld e,7
- ld a,$000F ;this is the only difference, means one less block than a line
- ld (BlockDiff),a
- call TestLine
- pop hl
- inc hl
- pop bc
- djnz Diag22
- ;this next have the same format, but different numbers
- ld hl,BlockMem+2
- ld e,3
- call TestLine
- ld hl,BlockMem+3
- ld e,4
- call TestLine
- ld hl,BlockMem+4
- ld e,5
- call TestLine
- ld hl,BlockMem+5
- ld e,6
- call TestLine
- ld hl,BlockMem+16+15
- ld e,6
- call TestLine
- ld hl,BlockMem+32+15
- ld e,5
- call TestLine
- ld hl,BlockMem+48+15
- ld e,4
- call TestLine
- ld hl,BlockMem+64+15
- ld e,3
- call TestLine
-
- ret ;returns with all common blocks tagged ( bit 7 set)
-
-
-
-
- ;----------------------------------------
- ;Call this with first address in hl, Difference between blocks in (BlockDiff)
- ;total blocks in line in e
- ;----------------------------------------
- ;During this routine, d=block count
- ; e=blocks to check, like a counter
- ; a=temporary variable
- ; hl=address of block being checked
- ; c=block to test against
- ; b=counter sometimes, bc temporary variable sometimes
- ;----------------------------------------
- TestLine:
- ld d,0 ;d starts at zero
- ld a,e ;load e into a to test against
- or a ;cp 0
- ret z ;if e is zero, blocks in line all checked
- ld a,(hl) ;gets block at address
- and %01111111 ;mask out top bit, tagged block possibly
- jr z,SkipZeroes ;if it's a zero, skip it, doesn't matter
- ld (StartBlock),hl ;that used as the first block in a possible series
- ld c,a ;c has the block to test against
- TestLine2:
- ld a,e ;check against e again
- or a
- jr z,TestLine3 ;if blocks all done, go here to see if you have three or more
- inc d ;block count so far
- push bc ;save bc, variables limited
- ld a,(BlockDiff) ;get difference between blocks in line
- ld c,a ;put it in bc
- ld b,0 ;like that
- add hl,bc ;and get the offset added to the previous block
- pop bc ;get bc back
- dec e ;we're done with one block, so decrement total
- ld a,(hl) ;get the next block
- and %01111111 ;mask out top bit, tagged block
- xor c ;check block with block being tested
- jr z,TestLine2 ;if same, keep going, we might have a line
- TestLine3: ;this checks if we have 3, if so, tags them
- ld a,d ;gets block count in common series
- inc a ;ease testing
- and %11111100 ;if it's 1 or 2, it won't count
- jr z,TestLine ;so if not 3 or more, go back and continue checking that line
- ld b,d ;blocks in common are used as counter here
- ld hl,(StartBlock) ;the starting block in the series
- TestLine4:
- set 7,(hl) ;tag it
- push bc ;save bc
- ld a,(BlockDiff) ;add the blockdifference again
- ld c,a
- ld b,0
- add hl,bc ;like that
- pop bc ;and get bc back
- ld a,(TotalBlockCount) ;counts total blocks tagged, used as score
- inc a ;increment it because one block tagged
- ld (TotalBlockCount),a ;save it
- djnz TestLine4 ;continue to tag all in the set
- jr TestLine ;continue with the next block in the line
-
- SkipZeroes:
- push bc ;save bc!
- ld a,(BlockDiff) ;add block diff again to get at next block
- ld c,a
- ld b,0
- add hl,bc
- pop bc ;get bc back
- dec e ;dec because one block skipped
- jr TestLine ;anc continue teseting
-
-
-
- ;-----------------------------
- ;This routine erases all blocks that
- ;are tagged (bit 7 set). It just erases them, doens't remove the tags
- DeleteBlocks:
- ld hl,BlockMem ;the first block
- ld de,$0000 ;first coords, (0,0)
- ld b,7 ;there are 7 rows
- DeleteBlocks2:
- push bc ;save that counter
- ld b,16 ;there are 16 rows
- DeleteBlocks3:
- push bc ;save that counter
- push de ;this puts de
- pop bc ;into bc for the routine DrawBlock
- bit 7,(hl) ;test for the tag
- jr z,DeleteBlocks4 ;if it is zero,( not tagged), then go here
- sub a ;blank block
- call DrawBlock ;this draws a blank block (sub a)
- DeleteBlocks4:
- inc hl ;this moves up the address
- inc d ;inc x coord
- pop bc ;get first counter
- djnz DeleteBlocks3 ;go back if not done with the row yet
- ld d,0 ;or... now we set the x coord back to zero
- inc e ;and inc the y coord
- pop bc ;retrieve this counter
- djnz DeleteBlocks2 ;and do the loop again
- ret ;get out of this function
-
-
- ;--------------
- ;this moves all the blocks down that are tagged and have been
- ;erased from the screen
- DropDown:
- ld hl,BlockMem ;first block...
- ld b,7 ;7 rows
- DropDown2:
- push bc ;save the counter
- ld bc,15 ;this is used as amount to move down, for the ldir
- DropDown3:
- bit 7,(hl) ;test the tag
- jr z,DropDown4 ;if it's not tagged, leave this place, or continue on...
- push hl ;this puts hl (the tagged block)
- pop de ;into de for the ldir
- inc hl ;goes to the next block for the ldir
- push bc ;save bc (will be changed by ldir)
- push hl ;save hl (will be cahnged by ldir)
- ldir ;this ldir moves all the blocks above the tagged block down
- ;one block, therefore erasing the tagged block
- pop hl ;retrieve hl
- dec hl ;and dec it because we had to inc it before
- pop bc ;retrieve bc, (saved from the ldir)
- add hl,bc ;we getting to the last block in the line
- ld (hl),$00 ;blank out the top block now that we've moved something
- or a ;reset carry flag
- sbc hl,bc ;gets back to the block we were on
- jr DropDown3 ;we're going to have to test teh same block again, because we
- ;just moved a different block into that position
-
- DropDown4: ;or... if not tagged
- inc hl ;move up to the next block
- dec bc ;moved up, so the blocks above it is decreased
- ld a,c ;check if c is zero yet
- or b ;by testing it against b (always zero)
- jr nz,DropDown3 ;if stuff still to do, go here
- inc hl ;go to the next line because at the end of the previous line
- pop bc ;the huge outer loop for each column
- djnz DropDown2 ;go if still more rows to do
- ret ;leave this friggin routine
-
-
-
- ;------------------
- ;called when it is detected that the set of three have hit the bottom
- FinishedSet:
- sub a ;make a zero
- ld (CurrFinished),a ;clear the indicator that shows whether set is done
- ld hl,(YCoord) ;we get the coords
- push hl
- pop bc ;and get them into bc
- call GetBlock ;so we can Get the address of the Block
- ld a,(CurrBot) ;hl is the address of the block
- ld (hl),a ;so load the block into the memory
- inc hl ;next block will just be one above
- ld a,(CurrMid) ;now we do the same with the middle one
- ld (hl),a ;there
- inc hl
- ld a,(CurrTop)
- ld (hl),a ;and the top one
- FinishedSet2:
- call BlockTestTime ;now that the mem is set, test all the blocks for matches
- call DeleteBlocks ;erase those blocks that are tagged by BlockTestTime
- ld de,$DFFF ;this is a small pause to make it look realistic
- FinishedSet3:
- dec de ;lower counter
- ld a,d ;or d
- or e ;with e
- jr nz,FinishedSet3 ;if something still there, continue with loop
- call DropDown ;now after delay, dropdown the blocks in mem
- call PutScreen ;and display the whole new screen
- ld a,(TotalBlockCount) ;this checks if there are more blocks to delete
- ld hl,(Score) ;add blocks to score
- ld c,a ;get a into bc
- ld b,0 ;like that
- add hl,bc ;add it to the score
- ld (Score),hl ;and put it back, yaah
- or a ;a still has the blocks deleted
- jr z,FinishedSet4 ;if it is zero (no blocks were deleted), jump to here
- ld de,$6FFF ;this goes back to check for more blocks after a pause
- lilloop:
- dec de ;this is the delay loop all over again
- ld a,d
- or e
- jr nz,lilloop
- jr FinishedSet2 ;and go back to check for more blocks
- FinishedSet4: ;all done, now last stuff
- ld hl,(Score) ;get score
- rl l ;these two commands rotate hl left once
- rl h ;you need to remember to grab the carry
- ld a,h ;we only want the info in h to test if 128 or more
- bit 3,a ;if there is more than 1024 points
- jr nz,GameAllDone ;go to GameAllDone
- ld (SpeedLevel),a ;the upper portion defines the speed
- rlca ;now we use the level to get the value for DelayTimer
- ld c,a ;put speed*2 into bc
- ld b,0 ;like that
- ld hl,TimerTable ;this is the table at the end of this program
- add hl,bc ;put the offset on
- call LD_HL_MHL ;get the value from that address
- ld (DelayTimer),hl ;and that is the timer value
-
- call UpdateLevel ;update the level on the screen
- call UpdateScore ;update the score on the screen
- ld bc,$0D03 ;this is the address of the block to test
- call GetBlock ;check that block to see if somethngs there
- or a ;if something there
- jr nz,GameAllDone ;if block in that position, game all done
- call MakeNewSet ;puts in random numbers for next 3
- call DrawCurrent ;and now we draw those three blocks
- jp keycheck ;and finally back to the main loop, yahoo!!!
-
-
-
- ;--------------
- ;Sets vars for the next three blocks
- MakeNewSet:
- ld hl,$0D03 ;sets coords for the new three
- ld (YCoord),hl ;set them
- ld hl,Rand1 ;the address of the three random variables
- ld de,CurrTop ;the address of the three current blocks
- ld bc,3 ;move three bytes
- ldir ;put randoms into the new blcoks
- ret
-
-
- ;-----------------
- ;Tests for high scores, enter them, or return if not high
- GameAllDone:
- sub a
- ld (SavedGame),a ;since game all done, no game is saved
- ld hl,(Score) ;get score
- ex de,hl ;we just want hl in de
- ld a,(LevelDiff) ;branches off relative to LevelDiff
- cp 3
- jr z,GameAllDone3
- cp 4
- jr z,GameAllDone4
- cp 5
- jr z,GameAllDone5
- cp 6
- jr z,GameAllDone6
- cp 7
- jr z,GameAllDone7
- jr GameAllDone8
-
-
-
- GameAllDone3: ;we're working on level 3
- ld hl,(High3) ;get the high score
- or a ;clear carry flag
- sbc hl,de ;because this subtraction includes the carry flag
- jp nc,Start ;but it sets the carry flag if subtraction went over
- ;if high is higher, go all the way back to start
- ex de,hl ;now put _your_ score in hl, it was in de
- ld (High3),hl ;and put in new high score
- ld hl,High3Name ;this is used later
- jr HighScoreTime ;and go to enter the initials
- GameAllDone4:
- ld hl,(High4) ;see above
- or a
- sbc hl,de
- jp nc,Start
- ex de,hl
- ld (High4),hl
- ld hl,High4Name
- jr HighScoreTime
- GameAllDone5: ;see above
- ld hl,(High5)
- or a
- sbc hl,de
- jp nc,Start
- ex de,hl
- ld (High5),hl
- ld hl,High5Name
- jr HighScoreTime
- GameAllDone6: ;see above
- ld hl,(High6)
- or a
- sbc hl,de
- jp nc,Start
- ex de,hl
- ld (High6),hl
- ld hl,High6Name
- jr HighScoreTime
- GameAllDone7: ;see above
- ld hl,(High7)
- or a
- sbc hl,de
- jp nc,Start
- ex de,hl
- ld (High7),hl
- ld hl,High7Name
- jr HighScoreTime
- GameAllDone8: ;see above
- ld hl,(High8)
- or a
- sbc hl,de
- jp nc,Start
- ex de,hl
- ld (High8),hl
- ld hl,High8Name
- jr HighScoreTime
-
-
- ;-----------------
- ;enters the high scores
- HighScoreTime:
- push hl ;saves the table to enter initials
- call _clrLCD ;first we clear the screen, dum, de, dum
- ld hl,$0500 ;this is place for text
- ld (_curRow),hl ;load it in
- ld hl,HighScore ;High Score!
- call _puts ;put string
- ld hl,$0801 ;place for first initial
- ld (_curRow),hl ;load it
- ld hl,StringPlace ;this has your previous high score, from UpdateScore
- call _puts ;put that score
-
- ld b,3 ;3 initials as counter
- ld hl,$0903 ;place to put first initial
- ld (_curRow),hl ;right there
- pop hl ;now this is the place to store initials, from before
- InputLoop:
- push bc ;save the counter
- push hl ;save place to store initials
- ld a,$DF ;this is ti-ascii for the cursor
- call _putc ;put the cursor
- ld hl,_curCol ;this is the after putting the cursor
- dec (hl) ;put it back to where the cursor is
- KeyLoop:
- call GET_KEY ;gets the key
- ld c,a ;get table value from InputTable
- ld b,0 ;
- ld hl,InputTable
- add hl,bc ;by adding the keyvalue to InputTable
- ld a,(hl) ;and get the value
- or a ;if it is zero
- jr z,KeyLoop ;we still need a key
- pop hl ;get the initial address back
- ld (hl),a ;and load the first initial
- inc hl ;and move to the next initial
- call _putc ;put that initial
- pop bc ;counter...
- djnz InputLoop ;and get all three
- ld de,$FFFF ;or not, at which point we set up a delay
- LoopWait:
- dec de ;you've seen this before
- ld a,d
- or e
- jr nz,LoopWait
- jp Start ;and all done, so go back to intro screen
-
-
-
- ;----------------
- ;puts the high score on the screen
- UpdateLevel:
- ld hl,$385D ;coords
- ld (_penCol),hl ;load in coord address
- ld a,(SpeedLevel) ;get the level
- add a,$31 ;this adds $30 to make it ascii, and one, to make it 1-8
- ld hl,StringPlace ;place to store ascii digit
- ld (hl),a ;put it in
- ld b,1 ;one char
- call _vputsn ;and display one char pointed to by hl
- ret
-
-
- ;----------------
- ;puts the score on screem
- UpdateScore:
- ld hl,$386B ;this is the cursor place
- ld (_penCol),hl ;and put it in
- ld hl,(Score) ;now we get score
- ld de,StringPlace+4 ;start of unpacking
- ld b,5 ;5 digits
- UpdateScore2:
- call UNPACK_HL ;divide hl by 10 and a contains remainder
- add a,'0' ;asciiize it
- ld (de),a ;put it in
- dec de ;next digit place to load
- djnz UpdateScore2 ;keep going
- ld hl,StringPlace ;now we put it back
- call _vputs ;and display the score
- ret
-
-
-
-
-
-
-
- ;---------------
- ;Draw the current three blocks
- DrawCurrent:
- ld hl,(YCoord) ;get coords...
- push hl ;
- pop bc ;in bc
- ld a,(CurrBot) ;get bottom block
- push bc ;save coords
- call DrawBlock ;and draw it
- pop bc ;get coords back
- inc b ;inc y coord
- ld a,(CurrMid)
- push bc ;and so forth
- call DrawBlock
- pop bc
- inc b
- ld a,(CurrTop)
- call DrawBlock
- ret
-
-
-
- ;---------------
- ;move the three down a notch
- MoveDown:
- ld hl,(YCoord) ;get coords
- ld a,h ;check x coord in a
- or a ;if xcoord zero, lowest possible
- jr z,IndicateFinish ;so indicate the finish, and leave
- dec h ;or else decrement x coord to check
- push hl ;
- pop bc ;put in bc
- call GetBlock ;this checks the block below, to see if it's done
- or a ;if so
- jr nz,IndicateFinish ;indicate the finish, and leave
- ld hl,(YCoord) ;if everything okay
- push hl ;save hl
- push hl ;put hl
- pop bc ;and get it in bc
- inc b ;go to the top block to erase that block
- inc b
- sub a ;blannk block
- call DrawBlock ;and draw it at the top
- pop hl ;coords saved
- dec h ;decrement it, xcoord
- ld (YCoord),hl ;and load them back
- call DrawCurrent ;Draw the Current three over the previous ones
- ret
- IndicateFinish:
- ld a,1 ;indiacte the finish with a boolean value
- ld (CurrFinished),a ;boolean to see if current set finished
- ret
-
-
-
- ;-------------
- ;This gets the value and address of the block specified by bc
- GetBlock:
- push bc ;save coords
- ld a,c ;use coord to find address
- rlca ;mult by 2
- rlca ;mult by 2
- rlca ;mult by 2
- rlca ;mult by 2 - 16 in all
- add a,b ;now we add the ycoord
- ld c,a
- ld b,0 ;put it in bc
- ld hl,BlockMem ;get the BlockMem
- add hl,bc ;and here's the address
- ld a,(hl) ;block ID in a,address in hl
- pop bc ;saves bc
- ret
-
-
- ;----------------
- ;Draws Block ID'd by a at coords b - (0-15) and c - (0-6)
- DrawBlock:
- push hl ;save hl
- push de ;save de
- push af ;save af which holds block
- rlc c ;mult y coord by 2
- ld e,c ;use as offset
- ld d,0
- ld hl,YTable ;add it to this table
- add hl,de ;like that
- call LD_HL_MHL ;now has hl row offset
- ld e,b ;now we put the x coord in de
- ld d,0
- add hl,de ;now added the column offset
- push hl ;and now we
- pop de ;put it in de
- pop af ;this gets the block we saved on the stack
- rlca ;mult by 8
- rlca
- rlca ;like that
- ld hl,Block0 ;now this contains all the blocks
- ld c,a ;put offset in bc
- ld b,0
- add hl,bc ;now hl points to the bitmap block
- ld b,8 ;8 bytes to display
- ex de,hl ;de now contains vidmem spot, hl contains table
- Putloop:
- push bc ;save counter
- ld a,(de) ;get the bitmap byte from program
- ld (hl),a ;put in vidmem
- inc de ;next byte
- ld bc,$0010 ;but we have to inc the vidmem 16 bytes to nextline
- add hl,bc ;like that
- pop bc ;now the counter again
- djnz Putloop ;and all eight bytes display
- pop de ;saves de and hl
- pop hl
- ret
-
- ;---------------------
- ;This routine displays the whole screen
- PutScreen: ;
- ld hl,BlockMem ;first block
- ld de,$0000 ;first coords
- ld b,7 ;7 rows
- PutScreen2:
- push bc ;save that counter
- ld b,16 ;16 rows
- PutScreen3:
- push bc ;save that counter
- push de ;put de
- pop bc ;in bc
- ld a,(hl) ;get that block!
- call DrawBlock ;saves de,hl, put block
- inc hl ;address
- inc d ;x coord
- pop bc ;get that counter
- djnz PutScreen3 ;loop till row finished
- ld d,0 ;xcoord zero
- inc e ;inc y coord
- pop bc ;and this counter
- djnz PutScreen2 ;and the outer loop
- ret ;screen all done
-
-
-
- LoadData:
- ld hl,$C089
- ld (hl),$12 ;variable type
- inc hl ;now to the next spot
- ld (hl),$07 ;the length
- inc hl ;now we put in the name
- push hl ;save that
- ld hl,searchwords ;here's the name of program
- pop de ;pop it back into de
- ld bc,7 ;seven bytes for the ldir
- ldir ;loads it into the spot
- rst 10h
- ld a,b
- ex de,hl
- call $4633
- set 6,a
- out (5),a
- inc a
- out (6),a
- ld bc,$4000
- or a
- sbc hl,bc
- push hl
- ld hl,CurrTop
- ld de,$D748
- or a
- sbc hl,de
- pop de
- add hl,de
- ld de,4
- add hl,de
- ld de,CurrTop
- ex de,hl
- ld bc,175
- ldir
- ld a,%00001101
- out (5),a
- ld a,%01000001
- out (6),a
- ret
-
-
- ;---------------------------------------------------------------------------
- ;End of code, start of data
-
-
- ;These are the strings
- ;FORMAT - .db "KOLLUMS 1.0",0
- ; ^ ^ ^
- ;this is 'define byte' ^ and a zero on the end for _puts or _vputs
- ; ^
- ; ^
- ; Here is the string with quotation marks
- ;
-
- TitleStr:
- .db "KOLLUMS 2.0",0
-
- Author:
- .db "By: Alan Bailey",0
-
- Email:
- .db "<bailela@charlie.cns.iit.edu>",0
-
- Difficulty:
- .db "Difficulty (l/r):",0
-
- HighScore:
- .db "High Score!",0
-
- HighStr:
- .db "High: ",0
-
- ResumeStr:
- .db "Press F1 to Resume Game",0
-
- searchwords:
- .db "kollums"
-
-
- ;This is the key table, takes the value from call GET_KEY
- ;and converts it to this ascii character
- InputTable:
- .db 0,0,0,0,0,0,0,0,0,0
- .db 'X','T','O','J','E',0,0
- .db ' ','W','S','N','I','D',0,0
- .db 'Z','V','R','M','H','C',0,0
- .db 'Y','U','Q','L','G','B',0,0,0,0
- .db 'P','K','F','A',0,0,0,0,0,0,0,0,0,0
-
-
- ;This is the value of the timers used to speed up the game
- TimerTable:
- .dw $0660,$05A0,$04E0,$0420,$0360,$02A0,$01E0,$0120
-
-
- ;7 y coord offsets for lookup
- YTable:
- .dw $FC00,$FC80,$FD00,$FD80,$FE00,$FE80,$FF00
-
- CurrTop:
- .db 0
- CurrMid:
- .db 0
- CurrBot:
- .db 0
- CurrFinished:
- .db 0
- Randomed:
- .db 0
- YCoord:
- .db 0
- XCoord:
- .db 0
- Rand1:
- .db 0
- Rand2:
- .db 0
- Rand3:
- .db 0
- StartBlock:
- .dw $0000
- TotalBlockCount:
- .db 0
- BlockDiff:
- .db 0
- DelayTimer:
- .dw $0660
- Score:
- .dw $0000
- SpeedLevel:
- .db 0
- StringPlace:
- .db 0,0,0,0,0,0
- BlockMem:
- .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- .db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-
-
-
- ;this variable is stored in the program because we want to save it
- LevelDiff:
- .db $06 ;this one we want to keep
-
- ;along with these high score variables
- High3:
- .db $01,$00
- High3Name:
- .db 'A','B','C',$00 ;plus zero terminator
- High4:
- .db $01,$00
- High4Name:
- .db 'D','E','F',$00
- High5:
- .db $01,$00
- High5Name:
- .db 'G','H','I',$00
- High6:
- .db $01,$00
- High6Name:
- .db 'J','K','L',$00
- High7:
- .db $01,$00
- High7Name:
- .db 'M','N','O',$00
- High8:
- .db $01,$00
- High8Name:
- .db 'P','Q','R',$00
-
- SavedGame:
- .db 0 ;set if a game is saved
-
-
- ;this are simple bitmaps of blocks
- Block0:
- .db %00000000
- .db %00000000
- .db %00000000
- .db %00000000
- .db %00000000
- .db %00000000
- .db %00000000
- .db %00000000
-
- Block1:
- .db %00000000
- .db %01111111
- .db %01000001
- .db %01000001
- .db %01000001
- .db %01000001
- .db %01000001
- .db %01111111
-
- Block2:
- .db %00000000
- .db %01111111
- .db %01111111
- .db %01111111
- .db %01111111
- .db %01111111
- .db %01111111
- .db %01111111
-
- Block3:
- .db %00000000
- .db %00001000
- .db %00011100
- .db %00111110
- .db %01111111
- .db %00111110
- .db %00011100
- .db %00001000
-
- Block4:
- .db %00000000
- .db %01100011
- .db %01100011
- .db %00010100
- .db %00001000
- .db %00010100
- .db %01100011
- .db %01100011
-
- Block5:
- .db %00000000
- .db %01010101
- .db %00101010
- .db %01010101
- .db %00101010
- .db %01010101
- .db %00101010
- .db %01010101
-
- Block6:
- .db %00000000
- .db %01111111
- .db %01001001
- .db %01001001
- .db %01111111
- .db %01001001
- .db %01001001
- .db %01111111
-
- Block7:
- .db %00000000
- .db %00001000
- .db %00010100
- .db %00100010
- .db %01000001
- .db %00100010
- .db %00010100
- .db %00001000
-
- Block8:
- .db %00000000
- .db %01111111
- .db %00111110
- .db %00011100
- .db %00001000
- .db %00011100
- .db %00111110
- .db %01111111
-
- .end ;tells TASM it's all over
-