quikman2k8.s

     1:  ; Quikman 2K8 for Commodore VIC20
     2:  ; written by Robert Hurst <robert@hurst-ri.us>
     3:  ; originally used Commodore VICMON (SYS 45056)
     4:  ; updated version: 29-Nov-2008
     5:  ;
     6:  ; to assemble this source using cc65.org project:
     7:  ;   ca65.exe --cpu 6502 --listing quikman2k8.s
     8:  ;   ld65.exe -C doc/vic20.cfg -o quikman2k8.prg quikman2k8.o
     9:  ;
    10:  ; to run the binary using viceteam.org project:
    11:  ;   xvic -memory none -ntsc -sound -joydev1 2 -autostart quikman2k8.prg
    12:  ; to run the binary using mess.org project:
    13:  ;   mess -view "Pixel Aspect (25:31)" vic20 -quik quikman2k8.prg
    14:  ;
    15:  ; pertinent VIC20 symbols
    16:  JIFFYH      = $A0       ; jiffy-clock hi byte value
    17:  JIFFYM      = $A1       ; jiffy-clock mid byte value
    18:  JIFFYL      = $A2       ; jiffy-clock low byte value
    19:  CLRPAGE     = $F4       ; color memory page (unexpanded = $97)
    20:  SCRNPAGE    = $0288     ; screen memory page (unexpanded = $1E)
    21:  CTRLCSHIFT  = $028D     ; keyboard flag: control/commodore/shift
    22:  CASSBUFF    = $033C     ; cassette buffer
    23:  VIC         = $9000     ; start of video interface chip registers
    24:  RESET       = $FD22     ; warm startup
    25:  CHROUT      = $FFD2     ; print character with cursor translation
    26:  GETIN       = $FFE4     ; get a character from keyboard queue
    27:  ;
    28:  ; my symbol / memory map
    29:  ;           = $00       ; base index (monster, sprite)
    30:  ;           = $01       ; index x2
    31:  ;           = $02       ; index x8
    32:  PPILLTIMER  = $10       ; powerpill effectiveness timer
    33:  FRUITTIMER  = $39       ; 0 - 242
    34:  FRUITFLAG   = $3A       ; zero or non-zero, if fruit has been activated
    35:  PPILLFLAG   = $3B       ; just ate a powerpill this turn (0=no)
    36:  CHOMP       = $3C       ; pointer into sound effect for fruit and fleeing monsters
    37:  CHEWING     = $3D       ; flag whether quikman just ate a dot or not
    38:  DIGIT       = $3E       ; award points at this digit place
    39:  POINTS      = $3F       ; how many points scored
    40:  OLDDIR      = $40       ; direction sprite was last moving in
    41:  NEWDIR      = $41       ; direction sprite wants to take, if valid by MAZEMOVE
    42:  JOYVAL      = $42       ; last joystick read value
    43:  QMANDIR     = $43       ; quikman's current direction (0=right,1=down,2=left,3=up)
    44:  FRAME       = $44       ; frame rate
    45:  LIVES       = $45       ; 0 - 3
    46:  FLASHPILL   = $46       ; powerpill blink counter (0-30)
    47:  EXTRAQMAN   = $47       ; bonus quickman flag (0=unused)
    48:  DEMOQMAN    = $48       ; spirit of quickman index (0-3)
    49:  FRUITLEVEL  = $49       ; 0 - 12
    50:  DOTS        = $4A       ; 0 - 174
    51:  PENALTY     = $4B       ; $4B-$4E monsters are free-to-roam flag
    52:  ;           = $4F       ; $4F-$52 monsters current direction (0=right,1=down,2=left,3=up)
    53:  ;           = $53       ; $53,$55,$57,$59 monster's knowledge of quikman's "X" coord was
    54:  ;           = $54       ; $54,$56,$58,$5A monster's knowledge of quikman's "Y" coord was
    55:  MONMOVE     = $61       ; $61-$64 monster array for its next best move
    56:  ;           = $69       ; temporary var
    57:  FLEEINGSCORE= $70       ; fleeing monster score: 2, 4, 8, 16
    58:  ;           = $F7       ; $F7/$F8,$F9,$FA are screen cell pointers for sprite's position
    59:  ;           = $FE       ; $FC/$FD,$FE/$FF are color cell pointers for same
    60:  ;
    61:  ; program indirects (my sprite registers)
    62:  SPRITE      = $02A1     ; bitmask 0-7 controls sprite on/off
    63:  SPRITEX     = $02A2     ; $02A2,A4,A6,A8,AA,AC,AE,B0 each "X" coordinate
    64:  SPRITEY     = $02A3     ; $02A3,A5,A7,A9,AB,AD,AF,B1 each "Y" coordinate
    65:  SPRITECLR   = $02B2     ; $02B2-$02B9 color
    66:  SPRITEIMG1  = $02BA     ; $02BA-$02C1 low-byte of SPRITE image
    67:  SPRITEIMG2  = $02C2     ; $02C2-$02C9 hi-byte of SPRITE image
    68:  SPRITELAST  = $02CC     ; $02CC-$02DC keep last state of SPRITE registers
    69:  SAVEBACK    = $02DD     ; $02DD-$02E6 keep what's under the sprite's 2-cell
    70:  ;
    71:  ; other constants
    72:  FRUITCELL   = $1F1B     ; screen cell address of fruit
    73:  FRUITCELLCLR= $971B     ; color cell address of fruit
    74:  ;
    75:  ; uses standard VIC20 (unexpanded)
    76:          .org $0FFF
    77:          .segment "STARTUP"
    78:  ;
    79:  ;********************************************************************
    80:  ; LOAD "QUIKMAN2K8.PRG",8,1
    81:          .word   $1001   ; starting load address
    82:  BASIC:  .byte   $0B, $10
    83:                  ; 2008 SYS4109
    84:          .byte   $D8, $07, $9E, $34, $31, $30, $39
    85:          .byte   $00, $00, $00
    86:  ;
    87:  ;********************************************************************
    88:  ; Main entry point into the game
    89:  START:
    90:          LDA #$08        ; lock uppercase / graphic set
    91:          JSR CHROUT
    92:          LDA VIC+$01
    93:          SBC #$04
    94:          STA VIC+$01
    95:          LDA #$80+$15    ; set for videoram @ $1E00 with 21-columns
    96:          STA VIC+$02     ; video matrix address + columns
    97:          LDA #$B0        ; $B0 = 10110000 = 24 rows + 8x8 height
    98:          STA VIC+$03     ; rows / character height
    99:          LDX #$FF        ; set for $1C00
   100:          STX VIC+$05     ; use programmable char set
   101:          JSR RESTORE
   102:          LDX #$16
   103:  @loop:  LDA BANNERMSG-1,X
   104:          STA BANNERMSG+$03FF,X
   105:          LDA #$03
   106:          STA BANNERMSG+$7BFF,X
   107:          DEX
   108:          BNE @loop
   109:          SEI
   110:          LDX #<BACKGROUND
   111:          LDY #>BACKGROUND
   112:          STX $0314       ; enable my IRQ vector jump
   113:          STY $0315
   114:          CLI
   115:  ;
   116:  RESTART:
   117:          JSR INITVARS
   118:          LDY #$00
   119:          STY LIVES
   120:          STY FRUITLEVEL
   121:          JSR GAMEOVER
   122:          LDY #$0A
   123:          STY SPRITE
   124:  @loop:  LDA FRAME
   125:          AND #$7F
   126:          BNE @slow
   127:          LDX VIC+$0F
   128:          INX
   129:          TXA
   130:          AND #$07
   131:          TAX
   132:          ORA #$08
   133:          STA VIC+$0F
   134:          JSR MAZEPAINT
   135:          LDA JIFFYM
   136:          AND #$0F
   137:          BNE @skip
   138:          STX PPILLFLAG   ; demo powerpill
   139:  @skip:  TAX
   140:          CPX #$0D
   141:          BCC @fruit
   142:          LDX #$00
   143:  @fruit: LDA FRUIT,X
   144:          STA FRUITCELL
   145:          LDA FRUITCLR,X
   146:          STA FRUITCELLCLR
   147:          LDA #$40
   148:          STA FRUITTIMER
   149:          STA FRUITFLAG
   150:  @slow:  LDX JIFFYL
   151:          INX
   152:          INX
   153:  @wait:  CPX JIFFYL
   154:          BNE @wait
   155:          LDA SPRITE
   156:          EOR #$1E
   157:          STA SPRITE
   158:          JSR NPC         ; demo mode
   159:  @scan:  JSR SPRITES
   160:          JSR GETIN       ; get keyboard
   161:          CMP #$03        ; got STOP ?
   162:          BNE @skip1
   163:          JMP RESET       ; bye-bye
   164:  @skip1: CMP #$88        ; got F7 ?
   165:          BNE @loop       ; try again ...
   166:  ;
   167:  ;********************************************************************
   168:  RESETGAME:
   169:          JSR INITVARS
   170:          LDA #$03        ; start with 3-lives
   171:          STA LIVES
   172:          LDY #$FF        ; -1 will become 0 at start of "next" level
   173:          STY FRUITLEVEL
   174:          JSR GAMEOVER    ; clear status
   175:          LDX #$00        ; reset score
   176:          STX EXTRAQMAN   ; reset bonus
   177:  @loop1: LDA #$B0        ; each digit to "0"
   178:          STA SCORE,X     ; into savebuffer
   179:          INX             ; do next digit
   180:          CPX #$06        ; all 6 of them
   181:          BNE @loop1
   182:  ;
   183:  STARTLVL:
   184:          JSR RESTORE     ; initialize new level
   185:  ;
   186:  RESETCHR:
   187:          LDX #$00
   188:          STX QMANDIR     ; start off going RIGHT
   189:          STX JOYVAL      ; preload last joystick value as going RIGHT
   190:  @loop1: LDA STARTPOS,X  ; reset each sprite starting position
   191:          STA SPRITEX,X
   192:          INX
   193:          CPX #$0A        ; 5 sprites per X,Y coordinate pair
   194:          BNE @loop1
   195:          LDA #$1D        ; 2nd page where quikman is on
   196:          STA SPRITEIMG2
   197:          LDA #$08        ; start quikman off with a smug smile
   198:          STA SPRITEIMG1
   199:          LDA #$1F        ; turn on sprites 0-4
   200:          STA SPRITE
   201:          LDA #$40
   202:          JSR PAUSE       ; then he sees there are monsters ...
   203:          LDX #$05
   204:  @loop2: LDA $C377,X     ; print READY from ROM
   205:          AND #$BF
   206:          ORA #$80
   207:          STA $1F18,X
   208:          LDA #$07        ; make it yellow
   209:          STA $9718,X
   210:          DEX
   211:          BNE @loop2      ; how geeky is that?
   212:          LDA #$58        ; quikman gets ready
   213:          STA SPRITEIMG1
   214:          LDA #$A0
   215:          JSR PAUSE       ; wait 2+ seconds
   216:          LDX #$00
   217:          LDA #$20        ; erase READY
   218:  @loop4: STA $1F19,X
   219:          INX
   220:          CPX #$05
   221:          BNE @loop4
   222:  ;
   223:  ; zero $39 - $43
   224:  ZEROVARS:
   225:          LDY #$39
   226:          LDX #$00
   227:  @loop:  STX $00,Y
   228:          INY
   229:          CPY #$44
   230:          BNE @loop
   231:  ;
   232:  ;********************************************************************
   233:  PLAYLOOP:
   234:          LDA CTRLCSHIFT  ; is the player holding down any
   235:          BNE PLAYLOOP    ; control, commodore, shift key(s)?
   236:          LDA FRUITCELL
   237:          CMP #$22        ; is there fruit on display?
   238:          BCC @warp
   239:          LDX FRUITLEVEL
   240:          LDA FRUITCLR,X  ; restore fruit color
   241:          STA FRUITCELLCLR
   242:  @warp:  LDA #$0C        ; 10-levels to warp
   243:          SEC
   244:          SBC FRUITLEVEL  ; progressive speed
   245:          BCC @cruz
   246:          CMP #$03
   247:          BCS @pace
   248:  @cruz:  LDA #$03
   249:  @pace:  JSR SLOWDOWN
   250:          STA $00         ; quikman is sprite #0
   251:          STA $01
   252:          LDA QMANDIR
   253:          STA OLDDIR      ; save last direction quikman was going in
   254:          LDX JOYVAL      ; recall last joystick value
   255:          STY $9113
   256:          LDA #$7F
   257:          STA $9122
   258:          LDA $9120
   259:          AND #$80        ; JOY 3
   260:          BNE @joy0
   261:          LDX #$00
   262:  @joy0:  LDA #$FF
   263:          STA $9122
   264:          LDY $9111
   265:          TYA
   266:          AND #$08
   267:          BNE @joy1
   268:          LDX #$01
   269:  @joy1:  TYA
   270:          AND #$10
   271:          BNE @joy2
   272:          LDX #$02
   273:  @joy2:  TYA
   274:          AND #$04
   275:          BNE @joy3
   276:          LDX #$03
   277:  @joy3:  STX JOYVAL      ; save
   278:          TXA
   279:          STA NEWDIR      ; do the same for the joystick
   280:          JSR MAZEMOVE
   281:          BCS @skip1      ; is the direction valid?
   282:          LDA JOYVAL      ; yes,
   283:          STA QMANDIR     ; request quikman to move in direction of joystick
   284:          CLC
   285:          BCC @skip2
   286:  @skip1: LDA QMANDIR
   287:          STA NEWDIR
   288:          JSR MAZEMOVE    ; keep the current direction going?
   289:  @skip2: LDA SPRITEX
   290:          BNE @skip3      ; is quikman at end of tunnel left?
   291:          LDA #$9E
   292:          STA SPRITEX     ; put quikman at beginning of tunnel right
   293:  @skip3: CMP #$A0        ; is quikman at end of tunnel right?
   294:          BNE @skip4
   295:          LDA #$00
   296:          STA SPRITEX     ; put quikman at beggining of tunnel left
   297:  @skip4: LDX #$00        ; use X as a flag
   298:          LDA SPRITEX
   299:          AND #$07
   300:          CMP #$04
   301:          BNE @skip5      ; is quikman in the middle of a left/right cell?
   302:          INX
   303:          LDA QMANDIR     ; yes, 0=right, 2=left
   304:          EOR #$02
   305:          TAY
   306:          BEQ @skip6      ; going left, use 1st saveback cell
   307:          DEY
   308:          BNE @skip6      ; going right, use overflow saveback cell
   309:  @skip5: LDA SPRITEY
   310:          AND #$07
   311:          CMP #$03
   312:          BNE @skip6      ; is quikman in the middle of an up/down cell?
   313:          INX
   314:          LDY QMANDIR
   315:          CPY #$01        ; going down, use overflow saveback cell
   316:          BEQ @skip6
   317:          LDY #$00        ; going up, use 1st saveback cell
   318:  @skip6: CPX #$00
   319:          BNE @skip7      ; does quikman have something in its mouth?
   320:          JMP NPCNEXT     ; no, continue play
   321:  @skip7: LDA SAVEBACK,Y  ; retrieve the character from quikman's saveback buffer
   322:          CMP #$20
   323:          BNE @skip8
   324:          JMP PLAYLOOP    ; nothing to eat here, so move a bit faster
   325:          ; check what was just eaten ...
   326:  @skip8: TAX             ; save that something in X
   327:          LDA #$20
   328:          STA SAVEBACK,Y  ; replace the cell quikman is on with an empty space
   329:          CPX #$1E        ; is it a dot?
   330:          BNE POWERUP
   331:          LDA #$01
   332:          STA POINTS      ; score 1
   333:          STA CHEWING     ; quikman has to chew this dot, monsters keep movin'
   334:          LDA #$0A        ; score it @ 10-point digit
   335:          STA DIGIT
   336:  ;
   337:  POWERUP:
   338:          CPX #$22
   339:          BCC @skip1      ; is X < 34 ?
   340:          CPX #$2A        ; no, is X >= 42 ?
   341:          BCS NPCNEXT     ; ate a piece of fruit?
   342:          TXA             ; YUMMY!
   343:          SEC
   344:          SBC #$22        ; strip off char code for score index
   345:          TAX
   346:          LDA FRUITSCORE,X
   347:          STA POINTS      ; award points
   348:          LDA #$09
   349:          STA DIGIT       ; in hundreds
   350:          STA CHOMP
   351:          CLC
   352:          BCC NPCNEXT
   353:  @skip1: CPX #$1F        ; ate a powerpill?
   354:          BNE EATING      ; no, but I did eat a dot
   355:          LDA #$05
   356:          STA POINTS      ; award 5-points
   357:          LDA #$0A
   358:          STA DIGIT       ; score @ 10-digit
   359:          STA PPILLFLAG
   360:          BEQ NPCNEXT     ; powerpills are dots on steroids, account for it
   361:  ;
   362:  EATING: INC DOTS        ; ate a dot, account for it
   363:          LDA DOTS
   364:          CMP #$AA        ; are all dots eaten?
   365:          BNE NPCNEXT
   366:  ;===    achieved end of level   ===
   367:  WONLEVEL:
   368:          LDA #$08        ; quikman ends with a smug smile
   369:          STA SPRITEIMG1
   370:          LDA #$80
   371:          JSR PAUSE
   372:          STA FRAME
   373:  @loop:  DEC FRAME
   374:          LDA FRAME
   375:          AND #$07
   376:          TAX
   377:          JSR MAZEPAINT
   378:          TXA
   379:          AND #$1F
   380:          BNE @next
   381:          LDA SPRITE
   382:          EOR #$1E
   383:          STA SPRITE      ; blink monsters
   384:          JSR SPRITES
   385:  @next:  LDA FRAME
   386:          CMP #$06
   387:          BNE @loop       ; continue until true blue
   388:          LDA #$40
   389:          JSR PAUSE
   390:          JSR INITVARS
   391:          LDX #$04
   392:  @loop1: LDA PENALTY-1,X
   393:          LDY FRUITLEVEL
   394:          INY
   395:  @loop2: LSR
   396:          DEY
   397:          BNE @loop2
   398:          STA PENALTY-1,X     ; after each level, the monsters dispatch quicker
   399:          DEX
   400:          BNE @loop1
   401:          JMP STARTLVL
   402:  ;
   403:  NPCNEXT:
   404:          JSR GETIN       ; get keyboard
   405:          CMP #$03        ; got STOP ?
   406:          BEQ WONLEVEL    ; CHEATER!!
   407:          JSR NPC
   408:          LDX #$50        ; closed mouth
   409:          LDA SPRITEX
   410:          ORA SPRITEY
   411:          AND #$02
   412:          BNE @anim
   413:          LDA QMANDIR     ; take 0=right,1=down,2=left,3=up value
   414:          ASL             ; multiply by 8 to get address
   415:          ASL
   416:          ASL
   417:          CLC
   418:          ADC #$58        ; add base offset
   419:          TAX
   420:  @anim:  STX SPRITEIMG1
   421:          JSR SPRITES
   422:          JMP PLAYLOOP
   423:  ;
   424:  ;********************************************************************
   425:  ; non-player characters & events
   426:  NPC:
   427:          LDA FRUITFLAG
   428:          BNE @skip3      ; is fruit already on display?
   429:          LDA DOTS
   430:          CMP #$4B        ; has the 75th dot been eaten?
   431:          BEQ @skip1
   432:          CMP #$7D        ; has the 125th dot been eaten?
   433:          BNE @skip3
   434:  @skip1: LDX FRUITLEVEL  ; prepare thy bonus
   435:          CPX #$0C        ; reach the last level?
   436:          BCC @skip2
   437:          LDX #$0C        ; only the key is left, and it leaves a bad metallic after-taste
   438:  @skip2: LDA FRUIT,X
   439:          STA FRUITCELL   ; display fruit
   440:          LDA FRUITCLR,X
   441:          STA FRUITCELLCLR
   442:          LDA #$FA        ; 250-moves and counting
   443:          STA FRUITTIMER  ; reset fruit timer
   444:          STA FRUITFLAG
   445:  @skip3: LDA FRUITTIMER  ; fruit is on display
   446:          BEQ @skip4      ; nothing to do
   447:          DEC FRUITTIMER  ; remove a tick
   448:          BNE @skip4      ; there is still time left
   449:          LDA #$20        ; time's up!
   450:          STA FRUITCELL   ; no more fruit
   451:  @skip4: LDA DOTS
   452:          CMP #$4C        ; has the 76th dot been eaten?
   453:          BEQ @skip5
   454:          CMP #$7E        ; has the 126th dot been eaten?
   455:          BNE @skip6
   456:  @skip5: LDA #$00
   457:          STA FRUITFLAG   ; more fruit potential on this level
   458:  ;
   459:  @skip6: LDA PPILLFLAG
   460:          BEQ KISSING     ; just swallowed a powerpill?
   461:          LDA #$00        ; account for that action
   462:          STA PPILLFLAG
   463:          LDA #$02        ; start scoring @ 200-points
   464:          STA FLEEINGSCORE
   465:          LDX FRUITLEVEL
   466:          TXA
   467:          AND #$07
   468:          BEQ @break      ; every 8-levels, keep timer up
   469:          CPX #$10
   470:          BCS @timer      ; 16-levels of powerpill timing
   471:          TXA
   472:  @break: ASL             ; x2
   473:          ASL             ; x2
   474:          AND #$3F
   475:          EOR #$3F        ; invert A
   476:          CPX #$05
   477:          BCC @timer      ; timer good to the 1st apple
   478:          LSR             ; 1/2
   479:  @timer: STA PPILLTIMER  ; set powerpill timer
   480:          LDY #$04
   481:  @loop1: LDX PENALTY-1,Y
   482:          BNE @skip7      ; is monster waiting in cage already?
   483:          LDA #$06        ; no, make monster blue
   484:          STA SPRITECLR,Y
   485:          LDA #$80        ; make monster fleeing (0)
   486:          STA SPRITEIMG1,Y
   487:          LDA $4E,Y
   488:          EOR #$02        ; and reverse its direction
   489:          STA $4E,Y
   490:  @skip7: DEY
   491:          BNE @loop1
   492:  ;
   493:  ; check all monsters if any are in contact with quikman
   494:  KISSING:
   495:          LDY #$08
   496:  KISSME:
   497:          LDA SPRITEX
   498:          CMP SPRITEX,Y
   499:          BNE @skip3
   500:          LDA SPRITEY
   501:          SEC
   502:          SBC SPRITEY,Y
   503:          BCS @skip2
   504:          EOR #$FF
   505:  @skip2: CMP #$05
   506:          BCS @skip3
   507:          LDX #$FF
   508:          BNE ENGAGED     ; is quikman engaged with a monster?
   509:  @skip3: LDA SPRITEY
   510:          CMP SPRITEY,Y
   511:          BNE NEXTKISS
   512:          LDA SPRITEX
   513:          SEC
   514:          SBC SPRITEX,Y
   515:          BCS @skip4
   516:          EOR #$FF
   517:  @skip4: CMP #$05
   518:          BCC ENGAGED     ; is quikman engaged with a monster?
   519:  ;
   520:  NEXTKISS:
   521:          DEY             ; next monster
   522:          DEY             ; X,Y coord pair check
   523:          BNE KISSME
   524:          JMP MONSTERS    ; quikman is still freely running!
   525:  ;
   526:  ENGAGED:
   527:          TYA
   528:          LSR
   529:          TAX
   530:          LDA SPRITEIMG1,X
   531:          CMP #$80        ; is monster fleeing?
   532:          BNE DEAD        ; no, quikman bites the dust
   533:          LDA #$09        ; ahah!  caught a little sickly one!
   534:          STA DIGIT       ; in hundreds
   535:          LDA FLEEINGSCORE
   536:          STA POINTS      ; fleeing monster score
   537:          ASL             ; next is worth x2 bonus
   538:          STA FLEEINGSCORE
   539:          LDA #$78
   540:          STA SPRITEIMG1,X ; reset monster as chasing
   541:          LDA #$51        ; reset "X" coord in cage
   542:          STA SPRITEX,Y
   543:          LDA #$58        ; reset "Y" coord in cage
   544:          STA SPRITEY,Y
   545:          LDA #$09
   546:          STA CHOMP
   547:          LDA JIFFYL
   548:  @loop1: CMP JIFFYL
   549:          BEQ @loop1      ; wait up to a jiffy
   550:          DEX
   551:          LDA MONSTERCLR,X
   552:          STA SPRITECLR+1,X
   553:          LDA CAGEDATA,X  ; load waiting room time
   554:          EOR #$FF
   555:          LSR
   556:          ADC #$20
   557:          STA PENALTY,X   ; monster is waiting
   558:          JMP NEXTKISS    ; is there another monster here?
   559:  ;
   560:  DEAD:
   561:          PLA             ; remove quikman's call to NPC from stack
   562:          PLA             ; because he just died . . .
   563:          LDA #$30
   564:          JSR PAUSE
   565:          ; death sequence
   566:          LDA #$01        ; only feature quikman dying
   567:          STA SPRITE
   568:          LDA #$50        ; low-order byte of 1st quikman image
   569:          STA SPRITEIMG1
   570:          LDA #$20
   571:          STA FRAME       ; rotate quikman 8 times
   572:  @loop1: LDA SPRITEIMG1
   573:          CMP #$70        ; are we at the 4th quikman image?
   574:          BCC @skip
   575:          LDA #$50        ; reset to 1st quikman image
   576:  @skip:  CLC
   577:          ADC #$08        ; advance to next image
   578:          STA SPRITEIMG1
   579:          LDA #$04
   580:          JSR PAUSE
   581:          DEC FRAME
   582:          BNE @loop1      ; repeat next sequence
   583:          LDX #$D8
   584:          LDY #$1C
   585:          STX SPRITEIMG1  ; explode!
   586:          STY SPRITEIMG2
   587:          LDA #$0A
   588:          JSR PAUSE
   589:          LDX #$E0
   590:          STX SPRITEIMG1  ; smoke!
   591:          LDA #$08
   592:          JSR PAUSE
   593:          LDX #$E8
   594:          STX SPRITEIMG1  ; dust!
   595:          LDA #$06
   596:          JSR PAUSE
   597:          JSR INITVARS
   598:          DEC LIVES
   599:          BEQ FINALITY    ; any lives remaining?
   600:          LDX LIVES
   601:          LDA #$20
   602:          STA $1FE4,X     ; erase the avatar
   603:          JMP RESETCHR    ; quikman still has life -- try again!
   604:  ;
   605:  FINALITY:
   606:          LDY LIVES
   607:          STY SPRITE
   608:          JSR GAMEOVER
   609:          LDA #$F0        ; 4-second pause
   610:          JSR PAUSE
   611:          JMP RESTART     ; this game is really over now
   612:  ;
   613:  ;********************************************************************
   614:  MONSTERS:
   615:          LDA #$04
   616:          STA $00         ; start with monster #4
   617:  ;
   618:  DOMONSTER:
   619:          LDA $00
   620:          TAY
   621:          ASL             ; x2
   622:          STA $01
   623:          LDX PENALTY-1,Y
   624:          BEQ ITMOVES     ; is this monster free to roam?
   625:          DEX             ; no, countdown to freedom
   626:          STX PENALTY-1,Y
   627:  ;
   628:  NEXTMONSTER:
   629:          DEC $00         ; process next monster
   630:          BNE DOMONSTER
   631:          INC FRAME
   632:          INC $00
   633:          LDA SPRITEY+$02
   634:          AND #$07
   635:          ORA SPRITEX+$02
   636:          AND #$0F
   637:          BEQ DOMONSTER
   638:          LDA CHEWING
   639:          BNE @skip1      ; is quikman eating a dot?
   640:  @fini:  RTS             ; no, we're done
   641:  @skip1: JSR SPRITES     ; yes, chasing monsters get another turn
   642:          JMP MONSTERS
   643:  ;
   644:  ITMOVES:
   645:          LDA FRAME
   646:          AND #$01
   647:          BEQ @cont       ; powerpill active?
   648:          LDA SPRITEIMG1,Y
   649:          CMP #$80        ; this monster IS fleeing
   650:          BEQ NEXTMONSTER ; skip its turn
   651:  @cont:  LDX $01         ; no, get pairing index
   652:          LDA SPRITEX,X
   653:          CMP #$50
   654:          BNE @skip1
   655:          LDA SPRITEY,X
   656:          CMP #$58
   657:          BNE @skip1      ; is monster in cage ($50,$58 coord) doorway ?
   658:          LDA #$57        ; could have just used DEC SPRITEY,X instead
   659:          STA SPRITEY,X   ; move it a pixel UP to force it through the closed door
   660:          LDX #$03
   661:          STX $4E,Y       ; make direction UP to get out of cage
   662:          BNE @skip3
   663:  @skip1: LDA SPRITEX,X
   664:          BNE @skip2      ; is monster against the left-side of the tunnel?
   665:          LDX $00
   666:          STA $4E,X       ; force a change of direction to the right
   667:  @skip2: CMP #$9F        ; is monster against the right-side of the tunnel?
   668:          BNE @skip3
   669:          LDX $00
   670:          LDA #$02
   671:          STA $4E,X       ; force a change of direction to the left
   672:  @skip3: LDY #$00
   673:          LDX #$04
   674:  @loop1: STX MONMOVE-1,Y ; preset move priority as 0=right,1=down,2=left,3=up
   675:          INY
   676:          DEX
   677:          BNE @loop1
   678:          LDY $01         ; start of monster's calculated move
   679:          LDA SPRITEX,Y
   680:          AND #$07
   681:          BEQ @skip4      ; is monster horizontally aligned with a screen cell?
   682:          LDA SPRITEY,Y
   683:          AND #$07
   684:          BNE @skip5      ; is monster vertically aligned with a screen cell?
   685:  @skip4: JSR AI          ; yes, check to see if a direction change is in its future
   686:          CLC
   687:          BCC @skip6
   688:  @skip5: LDX $4E,Y       ; not in a position to make a direction change,
   689:          STX $61         ; so just keep monster going in its current direction
   690:  @skip6: LDY #$00
   691:          STY $04
   692:  @loop2: LDX $61,Y
   693:          TXA
   694:          LDX $00
   695:          EOR $4E,X
   696:          CMP #$02
   697:          BEQ @skip7      ; don't allow monsters to reverse direction on their own
   698:          LDX $61,Y
   699:          STX NEWDIR
   700:          LDY $00
   701:          LDX $4E,Y
   702:          STX OLDDIR
   703:          JSR MAZEMOVE    ; validate
   704:          BCC MAKEMOVE    ; is this a good move?
   705:  @skip7: INC $04
   706:          LDY $04
   707:          CPY #$04
   708:          BNE @loop2
   709:          LDY $00         ; reverse direction
   710:          LDA OLDDIR
   711:          EOR #$02
   712:          STA $4E,Y
   713:          JMP NEXTMONSTER
   714:  ;
   715:  MAKEMOVE:
   716:          LDY $00         ; commit to this move
   717:          LDX NEWDIR
   718:          STX $4E,Y       ; save as monster's current direction
   719:          JMP NEXTMONSTER
   720:  ;
   721:  ; monster's artificial intelligence
   722:  AI:
   723:  ; first, preload $61-$64 with "best" moves this monster can make
   724:  ; to give quikman the kiss of death
   725:          LDX $01
   726:          LDA $51,X       ; retrieve this monster's "X" knowledge where quikman was
   727:          SEC
   728:          SBC SPRITEX,X
   729:          BCS @skip1
   730:          LDY #$02
   731:          STY MONMOVE     ; LEFT is best
   732:          LDY #$00
   733:          STY $64         ; RIGHT is worst
   734:          BEQ @skip2
   735:  @skip1: LDY #$00
   736:          STY MONMOVE     ; RIGHT is best
   737:          LDY #$02
   738:          STY $64         ; LEFT is worst
   739:  @skip2: LDA $52,X       ; retrieve this monster's "Y" knowledge where quikman was
   740:          SEC
   741:          SBC SPRITEY,X
   742:          BCS @skip3
   743:          LDY #$03
   744:          STY $62         ; UP is 2nd best
   745:          LDY #$01
   746:          STY $63         ; DOWN is 3rd best
   747:          BNE AI2
   748:  @skip3: LDY #$01        ; DOWN is 2nd best
   749:          STY $62
   750:          LDY #$03        ; UP is 3rd best
   751:          STY $63
   752:  ;
   753:  ; next, prioritize monster move, based upon its current location in respect to
   754:  ; its knowledge where quikman was considered last.
   755:  AI2:    LDX $01
   756:          LDA $51,X
   757:          SEC
   758:          SBC SPRITEX,X
   759:          BCS @skip1
   760:          EOR #$FF
   761:  @skip1: STA $69
   762:          LDA $52,X
   763:          SEC
   764:          SBC SPRITEY,X
   765:          BCS @skip2
   766:          EOR #$FF
   767:  @skip2: CMP $69
   768:          BCC @skip3      ; can monster improve upon order of choices?
   769:          LDX MONMOVE     ; swap 1st & 2nd choices
   770:          LDY $62
   771:          STX $62
   772:          STY MONMOVE
   773:          LDY $63         ; swap 3rd & 4th choices
   774:          LDX $64
   775:          STY $64
   776:          STX $63
   777:  @skip3: LDY $00
   778:          LDA SPRITEIMG1,Y
   779:          CMP #$80        ; is this monster fleeing?
   780:          BNE @fini       ; no, chase!
   781:          LDX #$04
   782:  @loop1: LDA MONMOVE-1,X
   783:          PHA
   784:          DEX
   785:          BNE @loop1
   786:  @loop2: PLA
   787:          STA $61,X       ; reverse logic when in flee mode
   788:          INX
   789:          CPX #$04
   790:          BNE @loop2
   791:  @fini:  RTS
   792:  ;
   793:  INITVARS:
   794:          LDY #$00
   795:  @loop:  LDX CAGEDATA,Y
   796:          STX PENALTY,Y
   797:          LDA STARTPOS,Y  ; reset each sprite starting position
   798:          STA SPRITEX,Y
   799:          INY
   800:          CPY #$10
   801:          BNE @loop
   802:          RTS
   803:  ;
   804:  ; restore sound/screen
   805:  RESTORE:
   806:          INC FRUITLEVEL
   807:          LDA #$00
   808:          STA SPRITE      ; turn off all sprites
   809:          LDA #$0E        ; black / blue
   810:          STA VIC+$0F     ; background / border color
   811:          LDA #$AF        ; pink & highest
   812:          STA VIC+$0E     ; auxiliary color & volume
   813:          LDA #$93        ; Shift-HOME is clearscreen
   814:          JSR CHROUT      ; print it
   815:          LDX #$15        ; skip 1st & last row
   816:  @draw:  LDA MAZEDATA,X
   817:          STA $1E00,X
   818:          LDA MAZEDATA+$EB,X
   819:          STA $1EEB,X
   820:          INX
   821:          BNE @draw
   822:          STX DOTS        ; and no dots are eaten (yet)
   823:          LDX #$06        ; blue
   824:          JSR MAZEPAINT
   825:          LDX #$00
   826:  @loop2: LDA QUIKMANCLR,X ; reset monsters starting colors
   827:          STA SPRITECLR,X ; into their sprite color registers
   828:          LDA #$78        ; reset monsters as chasing
   829:          STA SPRITEIMG1,X
   830:          LDA #$1D
   831:          STA SPRITEIMG2,X
   832:          INX
   833:          CPX #$05
   834:          BNE @loop2
   835:          LDY LIVES       ; paint lives remaining
   836:          JSR GAMEOVER
   837:          DEY
   838:          BEQ @next
   839:  @loop4: LDA #$2D        ; quikman character
   840:          STA $1FE4,Y     ; bottom-left of screen
   841:          LDA #$07        ; use yellow
   842:          STA $97E4,Y     ; and paint it
   843:          DEY
   844:          BNE @loop4
   845:  @next:  LDY FRUITLEVEL
   846:  @loop5: CPY #$0C        ; are we at the last level (key)?
   847:          BCC @skip1
   848:          LDY #$0C        ; only keys remain
   849:  @skip1: LDA FRUIT,Y     ; fruit character
   850:          STA $1FF1,X     ; bottom right of screen
   851:          LDA FRUITCLR,Y  ; get its color
   852:          STA $97F1,X     ; and paint it
   853:          CPY #$00        ; did we paint the cherry yet?
   854:          BEQ BEGIN       ; if so, we're done
   855:          INX
   856:          STX $FF
   857:          LDA FRUITLEVEL
   858:          SEC
   859:          SBC $FF
   860:          TAY
   861:          CPX #$07        ; no more than 7 fruits to display
   862:          BNE @loop5
   863:  BEGIN:  LDA LIVES       ; allow new screen to be processed
   864:          BEQ @cont
   865:          LDA #$40
   866:  @cont:  JSR PAUSE       ; by player
   867:          RTS
   868:  ;
   869:  ; recolor maze with some new paint in X
   870:  MAZEPAINT:
   871:          LDA #>MAZEDATA
   872:          STA @loop+2
   873:          LDA #$96
   874:          STA @color+2
   875:          LDY #$15
   876:  @loop:  LDA MAZEDATA,Y
   877:          CMP #$31
   878:          BCC @skip1
   879:          CMP #$3F
   880:          BCS @skip1
   881:          TXA
   882:  @color: STA $9600,Y
   883:  @skip1: INY
   884:          BNE @loop
   885:          INC @loop+2
   886:          INC @color+2
   887:          LDA @color+2
   888:          CMP #$98
   889:          BNE @loop
   890:          RTS
   891:  ;
   892:  ; if move is valid, carry flag will be clear on return
   893:  MAZEMOVE:
   894:          LDY $01         ; get X,Y coord index
   895:          LDA OLDDIR      ; get the last direction moving
   896:          AND #$01        ; mask UP/DOWN
   897:          BEQ @skip1      ; is direction LEFT/RIGHT?
   898:          INY             ; no, then fetch the "Y" coordinate
   899:  @skip1: LDA SPRITEX,Y   ; get one of sprite's coord
   900:          AND #$07
   901:          BEQ MAZEANY     ; at a crossroad?  check move in any 4-directions
   902:          LDA NEWDIR
   903:          CMP OLDDIR
   904:          BEQ MYMOVE      ; still want to move in the same direction?
   905:          EOR OLDDIR
   906:          CMP #$02
   907:          BEQ MYMOVE      ; is this a reverse direction request?
   908:          SEC             ; no new move made
   909:          RTS
   910:  ;
   911:  MAZEANY:
   912:          JSR SPRITEPREP
   913:          LDA $F8         ; reset screen hi-byte back into saved maze data
   914:          SEC
   915:          SBC #$04
   916:          STA $F8
   917:          LDX NEWDIR
   918:          CPX #$02
   919:          BCS @skip2      ; is X (2=left) or (3=up)?
   920:          LDA $F7         ; no
   921:          CLC
   922:          ADC PEEKAHEAD,X ; look (0=right) or (1=down)
   923:          BCC @skip1
   924:          INC $F8
   925:  @skip1: STA $F7
   926:          CLC
   927:          BCC @skip4      ; go validate
   928:  @skip2: LDA $F7
   929:          SEC
   930:          SBC PEEKAHEAD-2,X
   931:          BCS @skip3      ; look (2=left) or (3=up)
   932:          DEC $F8
   933:  @skip3: STA $F7
   934:  @skip4: LDY #$00        ; validate
   935:          LDA ($F7),Y
   936:          CMP #$31        ; is this direction into a maze wall?
   937:          BCC MYMOVE      ; good move?
   938:          RTS
   939:  ;
   940:  ; continue this sprite's move in whatever is loaded in NEWDIR
   941:  MYMOVE:
   942:          LDA NEWDIR
   943:          ASL             ; 0=0, 1=2, 2=4, 3=6, 4=8
   944:          TAX
   945:          LDY $01
   946:          LDA INERTIA,X
   947:          CLC
   948:          ADC SPRITEX,Y
   949:          STA SPRITEX,Y
   950:          LDA INERTIA+1,X
   951:          CLC
   952:          ADC SPRITEY,Y
   953:          STA SPRITEY,Y
   954:          CLC
   955:          RTS
   956:  ;
   957:  ;********************************************************************
   958:  ; my very own sprite routines
   959:  ; major custom hack for this maze game implementation
   960:  SPRITES:
   961:          LDA #$00        ; start with sprite #0
   962:          STA $00         ; current sprite # to render
   963:  @loop1: ASL
   964:          STA $01         ; current sprite (x2) pairing index
   965:          ASL
   966:          ASL
   967:          STA $02         ; current sprite (x8) image index
   968:          LDX $00
   969:          LDA SPRITE
   970:          AND SPRITEMASK,X
   971:          BEQ @skip2      ; nothing to do?
   972:          LDA SPRITELAST  ; what state was this sprite before?
   973:          AND SPRITEMASK,X
   974:          BEQ @skip1      ; it was "off"
   975:          JSR ERASESPRITE ; was "on" before, and we still want it "on"
   976:  @skip1: JSR SPRITEPREP  ; new sprite, go turn it "on"
   977:          JSR PREPMATRIX
   978:          JSR RENDER
   979:          JSR PLACEMATRIX
   980:          JMP @next
   981:  @skip2: LDA SPRITELAST
   982:          AND SPRITEMASK,X
   983:          BEQ @next       ; still nothing to do?  Then do nothing ...
   984:          JSR ERASESPRITE ; make this sprite disappear
   985:  @next:  INC $00
   986:          LDA $00
   987:          CMP #$05        ; only 5-sprites needed in this game
   988:          BNE @loop1
   989:          LDX #$00
   990:  @loop2: LDA SPRITE,X    ; save copy of current sprite registers
   991:          STA SPRITELAST,X
   992:          INX
   993:          CPX #$11        ; all 17 values, not including colors
   994:          BNE @loop2
   995:          RTS             ; fini
   996:  ;
   997:  ; remove sprite from screen
   998:  ERASESPRITE:
   999:          JSR LASTSPRITEPREP
  1000:          JSR PREPMATRIX
  1001:          JSR RESTOREMATRIX
  1002:          RTS
  1003:  ;
  1004:  LASTSPRITEPREP:
  1005:          LDA $01         ; 0, 2, 4, 6, 8
  1006:          CLC
  1007:          ADC #<SPRITELAST
  1008:          BNE SPRITEPREP2
  1009:  ;
  1010:  ; prepares the following registers:
  1011:  ; $F7/$F8,$F9/$FA       screen cell pointers for sprite position
  1012:  ; $FC/$FD,$FE/$FF       color cell pointers for same
  1013:  SPRITEPREP:
  1014:          LDA $01         ; 0, 2, 4, 6, 8 index
  1015:          CLC
  1016:          ADC #<SPRITE
  1017:  SPRITEPREP2:
  1018:          TAX             ; save this register index
  1019:          LDA $0201,X     ; get "X" coordinate
  1020:          CMP #$A0
  1021:          BCC @skip1      ; is "X" at or beyond last column?
  1022:          SBC #$A0        ; yes, subtract 160-pixels wide
  1023:  @skip1: LSR             ; and divide by 8-pixel width
  1024:          LSR
  1025:          LSR
  1026:          STA $F7         ; save column offset from left screen
  1027:          STA $FC         ; save column offset from left color
  1028:          LDA SCRNPAGE    ; get high order byte of screen memory page
  1029:          STA $F8
  1030:          LDA CLRPAGE     ; get high order byte of screen color page
  1031:          AND #$FE        ; make it and "even" number
  1032:          STA $FD         ; save high order
  1033:          LDA $0202,X     ; get "Y" coordinate
  1034:          CMP #$B8
  1035:          BCC @skip2      ; is "Y" at or beyond last row?
  1036:          SBC #$B8        ; yes, subtract 184-pixels high
  1037:  @skip2: LSR             ; and divide by 8-pixel height
  1038:          LSR
  1039:          LSR
  1040:          TAY
  1041:          BEQ @fini       ; if on top row, no math required
  1042:          LDA $F7         ; get column offset
  1043:  @loop1: CLC
  1044:          ADC #$15        ; add 21 for next row
  1045:          BCC @skip3      ; overflow to next page?
  1046:          INC $F8         ; yes, increment high order bytes
  1047:          INC $FD
  1048:  @skip3: STA $F7         ; save column offset
  1049:          STA $FC
  1050:          DEY
  1051:          BNE @loop1      ; do for each "row"
  1052:  @fini:  LDA $F8         ; copy high-order bytes
  1053:          STA $FA         ; for overflow sprite character
  1054:          LDA $FD         ; do the same
  1055:          STA $FF         ; for color
  1056:  ; determine whether overflow character is to the right or down
  1057:          LDA $0201,X     ; get "X" coordinate
  1058:          AND #$07
  1059:          BEQ @vert       ; 0 assumes moving up/down?
  1060:          LDA $F7         ; ok, moving left/right then ...
  1061:          CLC
  1062:          ADC #$01        ; make overflow character to the right
  1063:          BCC @savel
  1064:  @saveh: INC $FA
  1065:          INC $FF
  1066:  @savel: STA $F9         ; save character offset
  1067:          STA $FE         ; save color offset
  1068:          RTS
  1069:  @vert:  LDA $F7
  1070:          CLC
  1071:          ADC #$15        ; make overflow character below
  1072:          BCC @savel
  1073:          BCS @saveh
  1074:  ;
  1075:  ; prepares saveback buffers for restoring, should a larger-numbered sprite be
  1076:  ; overlapping any part of a smaller-numbered sprite
  1077:  PREPMATRIX:
  1078:          LDY #$00
  1079:          LDA ($F7),Y     ; retrieve screen cell
  1080:          PHA
  1081:          LDY $01         ; 0, 2, 4, 6, 8 index
  1082:          LDA $0201,X
  1083:          AND #$07
  1084:          BNE @2cell
  1085:          LDA $0202,X
  1086:          AND #$07
  1087:          BEQ @start
  1088:  @2cell: LDY #$00
  1089:          LDA ($F9),Y     ; retrieve overflow cell
  1090:          PHA
  1091:          LDY $01         ; 0, 2, 4, 6, 8 index
  1092:          INY
  1093:  @start: TYA
  1094:          TAX
  1095:  @loop:  PLA
  1096:  @retry: CMP $01
  1097:          BCC @skip       ; is A < ME ?
  1098:          CMP #$0A
  1099:          BCS @skip       ; is A >= MAX ?
  1100:  ; there is a sprite # greater than us on top ...
  1101:          TAY
  1102:          LDA SAVEBACK,Y  ; get > sprite# saveback info
  1103:          CLC
  1104:          BCC @retry
  1105:  @skip:  STA SAVEBACK,X
  1106:          DEX
  1107:          CPX $01
  1108:          BEQ @loop
  1109:          RTS
  1110:  ;
  1111:  ; restores the sprite's saveback buffer to the screen squares it occupies
  1112:  ; erasure part 3
  1113:  RESTOREMATRIX:
  1114:          LDX $01
  1115:          LDA SAVEBACK,X  ; recover character
  1116:          LDY #$00
  1117:          STA ($F7),Y     ; restore to screen
  1118:          LDA #$01
  1119:          STA ($FC),Y     ; just leave "white" behind
  1120:          LDA SPRITELAST+1,X
  1121:          AND #$07
  1122:          BNE @2cell
  1123:          LDA SPRITELAST+2,X
  1124:          AND #$07
  1125:          BEQ @fini
  1126:  @2cell: LDA SAVEBACK+1,X
  1127:          STA ($F9),Y     ; restore to screen
  1128:          LDA #$01
  1129:          STA ($FE),Y     ; only color overflow if X or Y are offset
  1130:  @fini:  RTS
  1131:  ;
  1132:  ; render sprite within its character matrix by merging its image over its saveback
  1133:  ; $05/$06 points to graphic character
  1134:  RENDER:
  1135:          LDX $00         ; 0-4
  1136:          LDA SPRITEIMG1,X
  1137:          STA $05
  1138:          LDA SPRITEIMG2,X
  1139:          STA $06
  1140:          LDX $01         ; 0,2,4,6,8
  1141:          LDA SPRITEY,X
  1142:          AND #$07
  1143:          STA $03
  1144:          TAX             ; X will hold the sprite's Y coord
  1145:          LDY #$00        ; erase temp image matrix area
  1146:          TYA
  1147:  @loop1: STA CASSBUFF+$20,Y
  1148:          INY
  1149:          CPY #$10        ; customized from 4 to 2 character cells
  1150:          BNE @loop1
  1151:          TAY             ; copy 8x8 character image into temp matrix
  1152:  @loop2: LDA ($05),Y     ; $05/$06 points to character matrix to draw
  1153:          STA CASSBUFF+$20,X
  1154:          INX
  1155:          INY
  1156:          CPY #$08
  1157:          BNE @loop2
  1158:          LDX $01
  1159:          LDA SPRITEX,X
  1160:          AND #$07        ; get modulos on X coordinate
  1161:          TAY
  1162:          BEQ @skip1      ; if its zero, no shifting required
  1163:  @loop3: LDX #$00
  1164:  @loop4: CLC
  1165:          ROR CASSBUFF+$20,X
  1166:          ROR CASSBUFF+$28,X
  1167:          INX
  1168:          CPX #$08
  1169:          BNE @loop4
  1170:          DEY
  1171:          BNE @loop3
  1172:  @skip1: STY $FB         ; Y is always zero here
  1173:  @loop5: LDA $01         ; index x2
  1174:          CLC
  1175:          ADC $FB
  1176:          TAX             ; X is sprite custom character
  1177:          LDA #$1C        ; 1st page is where sprites are stored
  1178:          STA $06
  1179:          LDA SAVEBACK,X
  1180:          CMP #$80
  1181:          BCC @skip2      ; is character reversed?
  1182:          LDY #$80        ; yes, use start of ROM character set
  1183:          STY $06
  1184:  @skip2: AND #$1F        ; get modulos of first 32-characters
  1185:          ASL             ; and multiply by 8-pixel height
  1186:          ASL
  1187:          ASL
  1188:          STA $05         ; save as low-order byte index
  1189:          LDA SAVEBACK,X
  1190:          AND #$60        ; mask 01100000
  1191:          LSR             ; divide by 16
  1192:          LSR
  1193:          LSR
  1194:          LSR
  1195:          LSR
  1196:          CLC
  1197:          ADC $06         ; add result to high-order page index
  1198:          STA $06
  1199:          LDY #$00
  1200:          LDA $FB
  1201:          ASL
  1202:          ASL
  1203:          ASL
  1204:          TAX
  1205:  @loop6: LDA ($05),Y     ; copy 8x8 character image into behind matrix
  1206:          STA CASSBUFF+$30,X
  1207:          INX
  1208:          INY
  1209:          CPY #$08
  1210:          BNE @loop6
  1211:          INC $FB
  1212:          LDA $FB
  1213:          CMP #$02        ; only a 2-cell sprite now
  1214:          BNE @loop5
  1215:          LDY #$00
  1216:          LDA $02         ; 0, 8, 16, 24, 32
  1217:          ASL             ; 0, 16, 32, 48, 64
  1218:          TAX
  1219:  @loop7: LDA CASSBUFF+$20,Y
  1220:          ORA CASSBUFF+$30,Y
  1221:          STA $1C00,X
  1222:          INX
  1223:          INY
  1224:          CPY #$10        ; customized from 4 to 2 character cells
  1225:          BNE @loop7
  1226:          RTS
  1227:  ;
  1228:  ; puts the sprite character matrix on the screen
  1229:  PLACEMATRIX:
  1230:          LDA $01         ; 0, 2, 4, 6, 8
  1231:          LDY #$00
  1232:          STA ($F7),Y
  1233:          LDX $00
  1234:          LDA SPRITECLR,X
  1235:          STA ($FC),Y
  1236:          LDX $01
  1237:          LDA SPRITEX,X
  1238:          AND #$07
  1239:          BNE @color
  1240:          LDA SPRITEY,X
  1241:          AND #$07
  1242:          BEQ @fini
  1243:  @color: LDA ($FC),Y
  1244:          STA ($FE),Y     ; only color overflow if X & Y are offset
  1245:          INX
  1246:          TXA
  1247:          STA ($F9),Y
  1248:  @fini:  RTS
  1249:  ;
  1250:  ;********************************************************************
  1251:  ; This section is dedicated to background processing, accomplished
  1252:  ; via the keyboard IRQ service, called 60-times per second (jiffy).
  1253:  BACKGROUND:
  1254:          LDA $1EDC
  1255:          CMP #$C5
  1256:          BNE @esc
  1257:          LDA #$09
  1258:          STA $96DC       ; paint the cage door
  1259:  @esc:   LDA JIFFYL
  1260:          AND #$07
  1261:          BNE FLASH
  1262:          LDA PPILLTIMER  ; drain powerpill
  1263:          BEQ FLASH       ; is there still power left?
  1264:          CMP #$1F        ; yes ... but are they
  1265:          BCS DRAIN       ; getting confidence back?
  1266:          AND #$03        ; yes, let's warn quikman
  1267:          BNE DRAIN
  1268:          LDY #$04
  1269:  @pp1:   LDA SPRITEIMG1,Y
  1270:          CMP #$80        ; is monster fleeing?
  1271:          BNE @pp2
  1272:          LDA SPRITECLR,Y
  1273:          EOR #$07        ; flash white / blue
  1274:          STA SPRITECLR,Y
  1275:  @pp2:   DEY
  1276:          BNE @pp1
  1277:  DRAIN:  DEC PPILLTIMER
  1278:          BNE FLASH
  1279:          LDY #$04
  1280:  @loop:  LDA MONSTERCLR-1,Y  
  1281:          STA SPRITECLR,Y ; restore all monsters to their default colors
  1282:          LDA #$78        ; restore monster chasing image (/)
  1283:          STA SPRITEIMG1,Y
  1284:          DEY
  1285:          BNE @loop
  1286:  FLASH:  LDA FLASHPILL   ; powerpill flash
  1287:          CMP #$1E        ; 30-jiffies?
  1288:          BNE @skip1
  1289:          LDX #$00        ; reset counter
  1290:          STX FLASHPILL
  1291:  @loop1: LDA $1CF8,X     ; custom graphic char
  1292:          EOR $8288,X     ; rom graphic char
  1293:          STA $1CF8,X     ; redraw 8x8 char cell
  1294:          INX
  1295:          CPX #$08
  1296:          BNE @loop1
  1297:          LDA #$FE        ; render monster feet
  1298:          EOR $1D7F       ; custom graphic char
  1299:          STA $1D7F       ; redraw agressive monster
  1300:          STA $1D87       ; redraw fleeing monster
  1301:  @skip1: INC FLASHPILL
  1302:          LDA LIVES
  1303:          BNE @hi         ; playing?
  1304:          LDA JIFFYL      ; manufacture a moving quikman 'spirit'
  1305:          AND #$03
  1306:          BEQ @hi
  1307:          CLC
  1308:          ADC JIFFYM
  1309:          AND #$03
  1310:          BEQ @hi
  1311:          INC DEMOQMAN
  1312:          LDA DEMOQMAN
  1313:          AND #$03
  1314:          ASL
  1315:          TAY             ; for the monsters to 'chase'
  1316:          LDA CAGEDATA+$08,Y
  1317:          STA SPRITEX
  1318:          LDA CAGEDATA+$09,Y
  1319:          STA SPRITEY
  1320:  @hi:    LDX #$00        ; yes
  1321:  @loop3: LDA SCORE,X     ; check current score against high score
  1322:          CMP MAZEDATA+$0F,X
  1323:          BCC @top        ; is quikman beating the high score?
  1324:          BNE @skip4      ; yes!
  1325:          INX
  1326:          CPX #$06
  1327:          BNE @loop3
  1328:  @skip4: LDX #$00
  1329:  @loop4: LDA SCORE,X     ; woot!
  1330:          STA MAZEDATA+$0F,X
  1331:          INX
  1332:          CPX #$06
  1333:          BNE @loop4
  1334:  @top:   LDX #$15        ; refresh top line
  1335:  @loop5: LDA MAZEDATA-1,X
  1336:          STA $1DFF,X
  1337:          DEX
  1338:          BNE @loop5
  1339:  ADDPTS: LDY POINTS      ; award points to score on screen
  1340:          BEQ CLRPTS
  1341:  @loop1: LDX DIGIT
  1342:  @loop2: LDA MAZEDATA,X
  1343:          CMP #$B9        ; reach "9" ?
  1344:          BEQ @skip2
  1345:          INC MAZEDATA,X  ; ding!
  1346:          DEY
  1347:          BNE @loop1
  1348:          BEQ CLRPTS
  1349:  @skip2: LDA #$B0
  1350:          STA MAZEDATA,X  ; wrap to "0"
  1351:          DEX             ; and increment next order
  1352:          BNE @loop2
  1353:  CLRPTS: STY POINTS
  1354:          LDX #$00
  1355:          LDY #$00
  1356:  @loop6: LDA PENALTY,X
  1357:          BNE @next       ; not aware while caged
  1358:          LDA DOTS
  1359:          CMP #$A6        ; make them all "smart" with 5-dots or less
  1360:          BCS @skip5
  1361:          LDA CAGEDATA,X
  1362:          BEQ @skip5      ; is monster "smart"?  Red one is ...
  1363:          CMP JIFFYL      ; no, so check as often as it waits
  1364:          BNE @next       ; is its wait time equal to the jiffy clock?
  1365:  @skip5: LDA SPRITEX     ; update this monster's awareness to where quikman is
  1366:          STA $53,Y
  1367:          LDA SPRITEY
  1368:          STA $54,Y
  1369:  @next:  INY
  1370:          INY
  1371:          INX
  1372:          CPX #$04
  1373:          BNE @loop6
  1374:  ;
  1375:  wahka:  LDA CHEWING
  1376:          BEQ @skip1
  1377:          LDA #$91        ; start with an odd frequency
  1378:          STA VIC+$0C     ; ignite a voice
  1379:  @skip1: LDA #$00        ; dot is swallowed
  1380:          STA CHEWING
  1381:          LDA VIC+$0C
  1382:          BEQ @next1      ; is this voice mute?
  1383:          LDA VIC+$0C
  1384:          AND #$01
  1385:          BEQ @skip3      ; is it even?
  1386:          LDA VIC+$0C
  1387:          CLC
  1388:          ADC #$10        ; increase tone
  1389:          CMP #$F1
  1390:          BCC @skip2      ; is voice too high?
  1391:          SEC
  1392:          SBC #$01        ; make it even
  1393:  @skip2: STA VIC+$0C
  1394:          CLC
  1395:          BCC @next1      ; goto next effect
  1396:  @skip3: LDA VIC+$0C
  1397:          SEC
  1398:          SBC #$10        ; drain tone
  1399:          STA VIC+$0C
  1400:  @next1: LDX CHOMP
  1401:          BEQ @skip4
  1402:          LDA JIFFYL
  1403:          AND #$01
  1404:          BNE @skip4
  1405:          LDA SNDBIT,X    ; load tone data
  1406:          STA VIC+$0B
  1407:          DEC CHOMP
  1408:  @skip4: LDA EXTRAQMAN
  1409:          BNE @fini       ; already got bonus life
  1410:          LDA SCORE+1
  1411:          CMP #$B1        ; did quikman just score 10,000-points?
  1412:          BNE @fini
  1413:          STA EXTRAQMAN
  1414:          LDX LIVES
  1415:          LDA #$2D
  1416:          STA $1FE4,X
  1417:          LDA #$07
  1418:          STA $97E4,X
  1419:          INC LIVES       ; reward
  1420:  @fini:  JMP $EABF       ; jump to hardware IRQ
  1421:  ;
  1422:  ; Pass A for number of jiffies to wait
  1423:  PAUSE:  STA @tick+1     ; rewrite CMP operand below
  1424:          JSR SPRITES     ; redraw sprites
  1425:          LDA JIFFYL
  1426:          STA $69         ; save this jiffy
  1427:  @loop:  LDA JIFFYL
  1428:          SEC
  1429:          SBC $69
  1430:  @tick:  CMP #$00        ; wait
  1431:          BNE @loop
  1432:          RTS
  1433:  ;
  1434:  ;********************************************************************
  1435:  ; Maze data ($1A00 - $1BFF)
  1436:  ; Screen size: 24-rows by 21-columns
  1437:          .res $1A00 - *
  1438:  MAZEDATA:
  1439:  SCORE   = * + $06
  1440:          .byte   $93, $83, $8F, $92, $85, $BA, $B0, $B0, $B0, $B0, $B0, $B0, $A0, $A0, $A0, $B0, $B2, $B0, $B0, $B0, $B0
  1441:          .byte   $37, $3A, $3A, $3A, $3A, $3A, $3A, $3A, $3A, $3A, $3D, $3A, $3A, $3A, $3A, $3A, $3A, $3A, $3A, $3A, $38
  1442:          .byte   $39, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $39, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $39
  1443:          .byte   $39, $1E, $37, $38, $1E, $37, $3A, $3A, $38, $1E, $39, $1E, $37, $3A, $3A, $38, $1E, $37, $38, $1E, $39
  1444:          .byte   $39, $1F, $35, $36, $1E, $35, $3A, $3A, $36, $1E, $32, $1E, $35, $3A, $3A, $36, $1E, $35, $36, $1F, $39
  1445:          .byte   $39, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $39
  1446:          .byte   $39, $1E, $33, $34, $1E, $31, $1E, $33, $3A, $3A, $3D, $3A, $3A, $34, $1E, $31, $1E, $33, $34, $1E, $39
  1447:          .byte   $39, $1E, $1E, $1E, $1E, $39, $1E, $1E, $1E, $1E, $39, $1E, $1E, $1E, $1E, $39, $1E, $1E, $1E, $1E, $39
  1448:          .byte   $35, $3A, $3A, $38, $1E, $3B, $3A, $3A, $34, $20, $32, $20, $33, $3A, $3A, $3C, $1E, $37, $3A, $3A, $36
  1449:          .byte   $20, $20, $20, $39, $1E, $39, $20, $20, $20, $20, $20, $20, $20, $20, $20, $39, $1E, $39, $20, $20, $20
  1450:          .byte   $3A, $3A, $3A, $36, $1E, $32, $20, $37, $3A, $3A, $C5, $3A, $3A, $38, $20, $32, $1E, $35, $3A, $3A, $3A
  1451:          .byte   $20, $20, $20, $20, $1E, $20, $20, $39, $20, $20, $20, $20, $20, $39, $20, $20, $1E, $20, $20, $20, $20
  1452:          .byte   $3A, $3A, $3A, $38, $1E, $31, $20, $35, $3A, $3A, $3A, $3A, $3A, $36, $20, $31, $1E, $37, $3A, $3A, $3A
  1453:          .byte   $20, $20, $20, $39, $1E, $39, $20, $20, $20, $20, $20, $20, $20, $20, $20, $39, $1E, $39, $20, $20, $20
  1454:          .byte   $37, $3A, $3A, $36, $1E, $32, $20, $33, $3A, $3A, $3D, $3A, $3A, $34, $20, $32, $1E, $35, $3A, $3A, $38
  1455:          .byte   $39, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $39, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $39
  1456:          .byte   $39, $1E, $33, $38, $1E, $33, $3A, $3A, $34, $1E, $32, $1E, $33, $3A, $3A, $34, $1E, $37, $34, $1E, $39
  1457:          .byte   $39, $1F, $1E, $39, $1E, $1E, $1E, $1E, $1E, $1E, $20, $1E, $1E, $1E, $1E, $1E, $1E, $39, $1E, $1F, $39
  1458:          .byte   $3B, $34, $1E, $32, $1E, $31, $1E, $33, $3A, $3A, $3D, $3A, $3A, $34, $1E, $31, $1E, $32, $1E, $33, $3C
  1459:          .byte   $39, $1E, $1E, $1E, $1E, $39, $1E, $1E, $1E, $1E, $39, $1E, $1E, $1E, $1E, $39, $1E, $1E, $1E, $1E, $39
  1460:          .byte   $39, $1E, $33, $3A, $3A, $3E, $3A, $3A, $34, $1E, $32, $1E, $33, $3A, $3A, $3E, $3A, $3A, $34, $1E, $39
  1461:          .byte   $39, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $1E, $39
  1462:          .byte   $35, $3A, $3A, $3A, $3A, $3A, $3A, $3A, $3A, $3A, $3A, $3A, $3A, $3A, $3A, $3A, $3A, $3A, $3A, $3A, $36
  1463:  BANNERMSG:      ; ©2008 RHURST  F7=PLAY
  1464:          .byte   $3F, $B2, $B0, $B0, $B8, $A0, $92, $88, $95, $92, $93, $94, $A0, $A0, $86, $B7, $BD, $90, $8C, $81, $99
  1465:  FRUITSCORE:
  1466:          .byte   $01, $03, $05, $07, $0A, $14, $1E, $32
  1467:  ;
  1468:  ;********************************************************************
  1469:  ; Custom character data -- must reside $1C00 - $1DFF
  1470:          .assert * = $1C00, error, "Graphics not at $1C00"
  1471:          .byte   $3E, $7C, $F8, $F0, $F0, $F8, $7C, $3E  ; @ sprite #0 - quikman
  1472:          .byte   $00, $00, $00, $00, $00, $00, $00, $00  ; A
  1473:          .byte   $38, $7C, $FE, $92, $FE, $FE, $FE, $AA  ; B sprite #1 - red
  1474:          .byte   $00, $00, $00, $00, $00, $00, $00, $00  ; C
  1475:          .byte   $38, $7C, $FE, $92, $FE, $FE, $FE, $AA  ; D sprite #2 - green
  1476:          .byte   $00, $00, $00, $00, $00, $00, $00, $00  ; E
  1477:          .byte   $38, $7C, $FE, $92, $FE, $FE, $FE, $AA  ; F sprite #3 - cyan
  1478:          .byte   $00, $00, $00, $00, $00, $00, $00, $00  ; G
  1479:          .byte   $38, $7C, $FE, $92, $FE, $FE, $FE, $AA  ; H sprite #4 - yellow
  1480:          .byte   $00, $00, $00, $00, $00, $00, $00, $00  ; I
  1481:  ;
  1482:  ;********************************************************************
  1483:  ; DATA
  1484:  QUIKMANCLR:     ; yellow
  1485:          .byte   $07
  1486:  MONSTERCLR:     ; red, green, cyan, yellow
  1487:          .byte   $02, $05, $03, $07
  1488:  CAGEDATA:       ;
  1489:          .byte   $00, $33, $76, $F9
  1490:          .byte   $02, $03, $02, $00
  1491:          .byte   $A0, $10, $00, $10, $A0, $B8, $00, $B8
  1492:  FRUIT:          ; cherry, strawberry, 2-peach, 2-apple, 2-pineapple, 2-tbird, 2-bell, key
  1493:          .byte   $22, $23, $24, $24, $25, $25, $26, $26, $27, $27, $28, $28, $29
  1494:  FRUITCLR:       ; red, red, 2-yellow, 2-red, 2-green, 2-magenta, 2-yellow, cyan
  1495:          .byte   $02, $02, $07, $07, $02, $02, $05, $05, $04, $04, $07, $07, $03
  1496:  GOTEXT:         ; GAME OVER
  1497:          .byte   $87, $81, $8D, $85, $A0, $8F, $96, $85, $92
  1498:  INERTIA:        ; maintain direction
  1499:          .byte   $01, $00, $00, $01, $FF, $00, $00, $FF
  1500:  PEEKAHEAD:      ;
  1501:          .byte   $01, $15
  1502:  STARTPOS:       ;
  1503:          .byte   $50, $88, $50, $48, $50, $58, $60, $58, $40, $58
  1504:  SNDBIT:         ; yummy sound effect
  1505:          .byte   $00, $00, $C0, $B8, $B0, $A8, $B0, $B8, $C0, $C8
  1506:  SPRITEMASK:     ; really?
  1507:          .byte   $01, $02, $04, $08, $10, $20, $40, $80
  1508:  ;
  1509:  ; Y > 0 erase; Y = 0 display
  1510:  GAMEOVER:
  1511:          LDX #$09
  1512:  @loop:  LDA GOTEXT-1,X  ; GAME OVER
  1513:          CPY #$00
  1514:          BEQ @dead
  1515:          LDA #$20        ; space
  1516:          STA BANNERMSG+$03FF,X
  1517:  @dead:  STA $1F16,X     ; print character
  1518:          STA $1B16,X
  1519:          LDA #$02
  1520:          STA $9716,X
  1521:          DEX
  1522:          BNE @loop
  1523:          RTS
  1524:  ;
  1525:  ; A contains governor - all registers are reset to zero
  1526:  SLOWDOWN:
  1527:          TAY
  1528:          TAX
  1529:  @sleep: INX
  1530:          BNE @sleep
  1531:          DEY
  1532:          BNE @sleep              ; one 1000, two 1000, three 1000, ...
  1533:          TYA
  1534:          RTS
  1535:  ;
  1536:  ; resume graphic character data
  1537:          .res $1CD8 - *
  1538:          .byte   $00, $10, $10, $6C, $10, $10, $00, $00  ; [ explosion
  1539:          .byte   $10, $44, $28, $C6, $28, $44, $10, $00  ; # smoke
  1540:          .byte   $92, $44, $00, $82, $00, $44, $92, $00  ; ] dust
  1541:          .byte   $00, $00, $00, $18, $18, $00, $00, $00  ; ^ dot
  1542:          .byte   $00, $3C, $7E, $7E, $7E, $7E, $3C, $00  ; <- powerpill (animated)
  1543:          .byte   $00, $00, $00, $00, $00, $00, $00, $00  ;$20 empty space
  1544:          .byte   $3C, $7E, $BD, $FF, $BD, $C3, $7E, $3C  ; ! smiley
  1545:          .byte   $04, $08, $18, $24, $62, $F7, $F2, $60  ; " cherry
  1546:          .byte   $10, $7C, $FE, $AA, $D6, $AA, $54, $28  ; # strawberry
  1547:          .byte   $20, $10, $7C, $FE, $FE, $FE, $7C, $38  ; $ peach
  1548:          .byte   $08, $10, $7C, $FE, $FE, $FE, $7C, $28  ; % apple
  1549:          .byte   $08, $10, $38, $38, $7C, $FE, $FE, $6C  ; & pear
  1550:          .byte   $10, $30, $92, $FE, $7C, $38, $10, $28  ; ' tbird
  1551:          .byte   $10, $38, $7C, $7C, $7C, $7C, $FE, $10  ; ( bell
  1552:          .byte   $18, $24, $18, $08, $08, $18, $08, $18  ; ) key
  1553:          .byte   $3C, $7E, $FF, $FF, $FF, $FF, $7E, $3C  ; * pacman closed
  1554:          .byte   $3E, $7C, $F8, $F0, $F0, $F8, $7C, $3E  ; + pacman right
  1555:          .byte   $3C, $7E, $FF, $FF, $E7, $C3, $81, $00  ; , pacman down
  1556:          .byte   $7C, $3E, $1F, $0F, $0F, $1F, $3E, $7C  ; - pacman left
  1557:          .byte   $00, $81, $C3, $E7, $FF, $FF, $7E, $3C  ; . pacman up
  1558:          .byte   $38, $7C, $FE, $92, $FE, $FE, $FE, $AA  ; / ghost chasing
  1559:          .byte   $38, $7C, $FE, $92, $FE, $82, $FE, $54  ; 0 ghost fleeing
  1560:          .byte   $00, $18, $24, $42, $42, $42, $42, $42  ; 1 maze wall north
  1561:          .byte   $42, $42, $42, $42, $42, $24, $18, $00  ; 2 maze wall south
  1562:          .byte   $00, $1F, $20, $40, $40, $20, $1F, $00  ; 3 maze wall west
  1563:          .byte   $00, $F8, $04, $02, $02, $04, $F8, $00  ; 4 maze wall east
  1564:          .byte   $42, $41, $40, $40, $40, $20, $1F, $00  ; 5 maze wall s-w elbow
  1565:          .byte   $42, $82, $02, $02, $02, $04, $F8, $00  ; 6 maze wall s-e elbow
  1566:          .byte   $00, $1F, $20, $40, $40, $40, $41, $42  ; 7 maze wall n-w elbow
  1567:          .byte   $00, $F8, $04, $02, $02, $02, $82, $42  ; 8 maze wall n-e elbow
  1568:          .byte   $42, $42, $42, $42, $42, $42, $42, $42  ; 9 maze wall vertical
  1569:          .byte   $00, $FF, $00, $00, $00, $00, $FF, $00  ; : maze wall horizontal
  1570:          .byte   $42, $41, $40, $40, $40, $40, $41, $42  ; ; maze wall west tee
  1571:          .byte   $42, $82, $02, $02, $02, $02, $82, $42  ; < maze wall east tee
  1572:          .byte   $00, $FF, $00, $00, $00, $00, $81, $42  ; = maze wall north tee
  1573:          .byte   $42, $81, $00, $00, $00, $00, $FF, $00  ; > maze wall south tee
  1574:          .byte   $3C, $42, $99, $A1, $A1, $99, $42, $3C  ;(C)copyright symbol
Valid XHTML 1.0 Strict
quikman2k8.html; generated on Sat Nov 29 13:24:24 2008 by ca65html
uz@cc65.org