;****************************************************************************; ;* *; ;* "Epsilon" *; ;* *; ;* Source Code (c) Copyright Paul Hughes 1989 *; ;* *; ;* Released into the Public Domain 30 June 2018. Do with it what you will. *; ;* If you make something with any of the code, a mention would be nice, but *; ;* isn't by any means required. *; ;* *; ;* I'll happily try to explain things, but remember the code is almost 30 *; ;* years old, the understanding of the C64 has come a long way, and it was *; ;* written by a somewhat hubristic 20 year old me. *; ;* *; ;****************************************************************************; ; SIN table @ $0D00-$0DFF ; COS table @ $0E00-$0EFF ; Char set @ $0500-$0CFF ; Sprites @ $D000-$FFF9 ; Code @ $0F00-$???? ; Standard condition variables TRUE EQU 1 FALSE EQU 0 YES EQU TRUE ;NO EQU FALSE SHOW_RASTER EQU NO ; Display game raster time in borders SCREEN1 EQU $C800 ; 1st screen base address SCREEN2 EQU $CC00 ; 2nd " " " CIRCLE_X EQU $0D00 ; Circle X coordinate address CIRCLE_Y EQU $0E00 ; " Y " " BLACK EQU 0 ; C64 colour codes WHITE EQU 1 RED EQU 2 CYAN EQU 3 PURPLE EQU 4 GREEN EQU 5 BLUE EQU 6 YELLOW EQU 7 ORANGE EQU 8 BROWN EQU 9 PINK EQU 10 DGREY EQU 11 MGREY EQU 12 LGREEN EQU 13 LBLUE EQU 14 LGREY EQU 15 ; CHANGE_FRAME EQU 255 ; POWER_UP EQU $80 ; Flag to indicate power up capsule ATTR EQU $8000 ; Map attribute address BLOCKSTART EQU $A000 ; Map block base address MAPSTART EQU $8100 ; Map data base address MAPEND EQU MAPSTART+MAPH*MAPW ; Map data end address MAPH EQU 210 ; Map height in blocks MAPW EQU 10 ; Map width in blocks STARTPOS EQU MAPH*4 ; Start position within the map FIN EQU 0 NOFIRE EQU 0 LINE EQU 1 OCTO EQU 2 SPY EQU $D001 ; Vic chip sprite Y base SPX EQU $D000 ; Vic chip sprite X base SPC EQU $D027 ; Vic chip sprite colour base RASTDIF EQU 21 ; Plexor time before new raster NSP EQU 31 ; Number of sprites ZP EQU 02 ; Zero page base address ORG ZP IA DFB 0 ; Interrupt temps IX DFB 0 ; " " IY DFB 0 ; " " SY DFS NSP,0 ; Sprite Y SX DFS NSP,0 ; Sprite X SPRC DFS NSP,0 ; Sprite colour SPRCHR DFS NSP,0 ; Sprite pointer PNT1 DFS NSP,0 ; Pointer within Sprite Y TX DFB 0 ; Temporary TY DFB 0 ; " " CNT DFB 0 ; Multiplexor shift depth variable RASTEMP DFB 0 ; Accumulated M/PLEX raster depth NXTSP DFB 0 ; Next multiplexor sprite NXTSPR DFB 0 ; Next Vic sprite DATABASE DFW 0 ; Indirect baddy data address FROM DFW 0 ; General pupose FROM indirect addr TO DFW 0 ; " " TO " " MAP DFW 0 ; Indirect address within the map BLOCK DFW 0 ; Indirect block address NMIA DFB 0 ; NMI temporary SCX DFW 0 ; Indirect address within high scores FROMM DFW 0 ; Standard indirect variable addresses FROM2 DFW 0 ; " " " " TO2 DFW 0 ; " " " " SPRITE DFW 0 ; Current sprite address being mutated PC.A DFW 0 ; Music driver program counter A PC.B DFW 0 ; " " " " B PC.C DFW 0 ; " " " " C READ_A DFW 0 ; Music driver arpeggio address A READ_B DFW 0 ; " " " " B READ_C DFW 0 ; " " " " C PC.D DFW 0 ; Music driver drum program counter TEMP_VOL DFB 0 ; Temporary music volume status WINDOW_MES DFW 0 ; Indirect address of status message CALC DFW 0 ; Indirect caclulation address ORG $0200 ; ; General purpose variables ; ; ; All variables to be reset to Zero ; VSTART READY_ON DFB 0 ; If "GET READY" should be displayed READY_TIMER DFB 0 ; "GET READY" display time WEAPON_PENDING DFB 0 ; Flag for new weapon waiting NEW_WEAPON DFB 0 ; New weapon number LASER_ON DFB 0 ; Laser active flag LASER_LENGTH DFB 0 ; Current length of the laser WEAPON DFB 0 ; Current weapon in use LIVES DFB 0 ; Number of lives remaining SCROLL_FLAG DFB 0 ; Scroll active flag SX_BUFFER DFS NSP,0 ; Sprite X buffer SY_BUFFER DFS NSP,0 ; Sprite Y buffer SCRBASE DFB 0 ; Current screen page pointer BLOCKINDEX DFB 0 ; Index within map block DECODEFLAG DFB 0 ; Flag to signal decode needed COLOURFLAG DFB 0 ; Flag to signal colour scroll needed COUNT DFB 0 ; Counter for width of block COLBUF DFS 40,0 ; Buffer to store middle colour band POS DFB 0 ; Hardware scroll position DELAYFLAG DFB 0 ; Flag to sync MAIN_LOOP to raster JOYTEMP DFB 0 ; Temporary store of joystick position ALNUM DFB 0 ; Store of no of aliens in formation TEMP DFB 0 ; Temporary stores TEMPX DFB 0 ; " " TEMPY DFB 0 ; " " PODDEL DFB 0 ; Delay between pos animation phases XDIF DFB 0 ; Source-destination linedraw distance YDIF DFB 0 ; " " " " PULSETIME DFB 0 ; Delay between pulsing bullets PULSEIND DFB 0 ; Index within bullet pulse table ALIENS EQU 10 ; Maximum aliens on the screen ALIENON DFS ALIENS,0 ; Alien active flag INTROCOUNT DFS ALIENS,0 ; Alien introduction counters YVEL DFS ALIENS,0 ; Alien Y velocities XVEL DFS ALIENS,0 ; Alien X velocities BADDYCOUNT DFS ALIENS,0 ; Alien velocity counter BADDYX DFS ALIENS,0 ; Alien initial X coordinate ANIML DFS ALIENS,0 ; Animation table address Low byte ANIMH DFS ALIENS,0 ; " " " High byte PATHSL DFS ALIENS,0 ; Alien flight path address Low byte PATHSH DFS ALIENS,0 ; " " " " High byte INTROTEMP DFS ALIENS,0 ; Alien pre introduction temp BADDYXTEMP DFS ALIENS,0 ; Alien pre introduction temp BADDYCUL DFS ALIENS,0 ; Alien pre introduction colour BADDYCOLOUR DFS ALIENS,0 ; Alien colour ADDRTEMPL DFS ALIENS,0 ; Alien flight path pre-intro address ADDRTEMPH DFS ALIENS,0 ; " " " " " DESTROYSHOTS DFS ALIENS,0 ; No of shots required to kill alien EXPLODE_FLAGS DFS ALIENS,0 BANG_TIME DFS ALIENS,0 ; Delay between baddy explosion frames BULTYPE DFS ALIENS,0 ; The type of bullet the alien fires BULCOUNT DFS ALIENS,0 ; Counter between firing next bullet BULCOUNT2 DFS ALIENS,0 ; Variable count " " " ANIMINDEX DFS ALIENS,0 ; Index within alien animation table ANIMSPEED DFS ALIENS,0 ; Counter between next alien frame ANIMSPEED2 DFS ALIENS,0 ; Variable count " " " ANIMATION_HALT DFS ALIENS,0 ; Animation program active flag LEAVE_FLAGS DFS ALIENS,0 ; Leave behind flags ! BULLETS EQU 8 ; Maximum alien bullets on the screen BULON DFS BULLETS,0 ; Alien bullet active flag BULLINTX DFS BULLETS,0 ; Bullet X integer BULLINTY DFS BULLETS,0 ; Bullet Y integer BULVAR DFS BULLETS,0 ; Variable bullet additive BULST DFS BULLETS,0 ; Constant bullet additive DIRX DFS BULLETS,0 ; Bullet X direction DIRY DFS BULLETS,0 ; Bullet Y direction LOCKED_STUFF EQU NSP ; Number of objects locked maximum LOCKON DFS LOCKED_STUFF,0 ; Locked to the background flags VERPOS DFW 0 ; Vertical position in the map MAPCOUNT DFW 0 ; Map counter for alien triggering FIREFLAG DFS 4,0 ; Player ship fire flags PLRSC DFB $00,$00,$00 ; Player 1's score VEND BS1 DFB 1,2,4,8 ; Bit masks DFB 16,32,64,128 NB1 DFB $FE,$FD,$FB,$F7 ; " " DFB $EF,$DF,$BF,$7F ONCE_FLAG DFB 0 ; Flag for doing credits HALFPIX DFB 2 ; Half pixel scroll counter ORG $0F00 ; ENT ; ; GAME_START - The start point for the game, nothing preserved (!) ; GAME_START SEI ; Stop interrupts LDX #$FF TXS ; Reset the stack LDA #$35 ; Roms out STA 1 LDA #$1B ; Screen on STA $D011 JSR SETBANK ; Set into Display Bank 3 ($C000) JSR SETRAST ; Initialise raster interrupts JSR SETNMI ; Initialise Non maskable interrupts ; JSR GRAB_CHARS ; Grab the charset required WARMSTART JSR CLS ; Clear both screens JSR CLRVARS ; Reset all variables JSR SETUP ; Initialise multiplexor JSR GAME_SETUP ; Initialise non-zero variables JSR DELAY ; Allow rasters to sync (!) JSR DELAY JSR DELAY ; Tacky !!! JSR DELAY JSR CLEAR_WORKSET JSR DUMP_SCREEN ; Dump a lump of map on the screen ; LDA #$60 ; Point fade routines to charset ; STA CHAR_BASE+1 ; STA CHAR_BASE_2+1 ; JSR FADE_IN JSR GRAB_CHARS LDX #0 ; Initialise the in game tune JSR TUNE STX DELAYFLAG ; Zeroise synchroniser INX STX SCROLL_FLAG ; Enable scroll LDA #3 ; Weapon test ! STA WEAPON JSR SET_READY ; Initialise "GET READY" logo ; ; MAIN_LOOP - The game main control loop ; MAIN_LOOP JSR DELAY ; Lock loop to raster JSR DECODE ; Decode the map to the screen JSR COLOUR_SCROLL ; Scroll the Colour Ram JSR JOY ; Read the joystick JSR COLLECT_ICON ; Picks up any power-ups ; JSR CHANGE_WEAPON ; Changes to new weapon JSR DOBULLETS ; Process player bullets JSR BADDIES ; Process baddy attack patterns JSR ANIMATEBADS ; Animate baddies JSR BADDYBULS ; Process baddy bullets JSR REFRESH ; Process the in-game music JSR HIT_BADDIES ; Collision towards baddies JSR EXPLODE_BADDY ; Procceses alien explosions JSR PROCESS_READY ; Displays "GET READY" if needed LDA #63 ; Check if RUN/STOP has been JSR KEYSCAN BCS ABORT ; pressed LDX #$00 ; Just for a test... LDY #$01 ; add 1 to player 1's score JSR ADD_POINTS JMP MAIN_LOOP ; And back to the top ABORT JSR CLEAR_WORKSET SEI LDA #$7F STA $DC0D STA $DD0D LDA $DC0D LDA $DD0D LDX #1 STX $D01A DEX STX $DD0E LDA #$0F STA $D019 JMP TITLE_SEQUENCE ; Game aborted ; ; SETRAST - Initialise raster interrupts ; SETRAST SEI LDA #R0 STA $FFFE LDA ^R0 STA $FFFF LDA #$F8 STA $D012 LDA #$7F AND $D011 STA $D011 STA $DC0D STA $DD0D LDA $DC0D LDA $DD0D LDX #1 STX $D019 STX $D01A CLI RTS ; ; SETNMI - Initialise game Non maskable interrupts ; SETNMI LDA #NMI1 STA $FFFA LDA ^NMI1 STA $FFFB LDA #$81 STA $DD0D RTS ; ; NMI1 - First NMI, triggers the colour scroll & resyncs the MAIN_LOOP ; NMI1 STA NMIA LDA $DD0D IF SHOW_RASTER=TRUE LDA $D020 PHA LDA #2 STA $D020 ELSE LDA POS ; Check for last scroll update CMP #7 BNE NOCOLSCR LDA HALFPIX ; Check if half pixel has occuured CMP #2 BEQ NOCOLSCR LDA #1 ; If so trigger the colour scroll STA COLOURFLAG INC DELAYFLAG ; Resync the main loop to the middle NOCOLSCR IF SHOW_RASTER=TRUE PLA STA $D020 ELSE LDA NMIA RTI ; ; SMOOTH - Processes the hardware scroll, controls Screen Page Flipping ; and sprite background locking ; SMOOTH LDA SCROLL_FLAG ; Is the scroll enabled ? BNE SCROLL_ENABLED RTS SCROLL_ENABLED DEC HALFPIX ; Every BEQ GODOWN RTS GODOWN LDA #2 STA HALFPIX IF SHOW_RASTER=TRUE DEC $D020 ELSE JSR LOCK ; Lock sprites to the background IF SHOW_RASTER=TRUE INC $D020 ELSE LDA POS ; Add 1 to scroll position ADD #1 AND #7 STA POS BEQ CHANGE RTS CHANGE LDA SCRBASE ; Flip Page address EOR #$10 STA SCRBASE LDA #1 ; Set the screen decode flag STA DECODEFLAG RTS ; ; SCROLL - Builds a new screen scrolled down over 8 frames ; SCROLL LDA SCROLL_FLAG BNE OK_SCR RTS OK_SCR LDA SCRBASE ; Which screen to write to AND #$10 BEQ WRITE48 WRITE4C LDA POS ASL TAX LDA DOWHAT4C+0,X STA JUMPIN+1 LDA DOWHAT4C+1,X STA JUMPIN+2 JUMPIN JMP $AAAA ; Self Modified WRITE48 LDA POS ASL TAX LDA DOWHAT48+0,X STA JUMPIN2+1 LDA DOWHAT48+1,X STA JUMPIN2+2 JUMPIN2 JMP $AAAA ; Self Modified DOWHAT48 DFW SC148 ; Which scroll routine to use DFW SC248 DFW SC348 DFW SC448 DFW SC548 DFW SC648 DFW SC748 DFW SC848 DOWHAT4C DFW SC14C DFW SC24C DFW SC34C DFW SC44C DFW SC54C DFW SC64C DFW SC74C DFW SC84C SC148 LDX #$27 LOOP1 LDA SCREEN1+24*40,X STA SCREEN2+25*40,X LDA SCREEN1+23*40,X STA SCREEN2+24*40,X LDA SCREEN1+22*40,X STA SCREEN2+23*40,X DEX BPL LOOP1 RTS SC248 LDX #$27 LOOP2 LDA SCREEN1+21*40,X STA SCREEN2+22*40,X LDA SCREEN1+20*40,X STA SCREEN2+21*40,X LDA SCREEN1+19*40,X STA SCREEN2+20*40,X DEX BPL LOOP2 RTS SC348 LDX #$27 LOOP3 LDA SCREEN1+18*40,X STA SCREEN2+19*40,X LDA SCREEN1+17*40,X STA SCREEN2+18*40,X LDA SCREEN1+16*40,X STA SCREEN2+17*40,X DEX BPL LOOP3 RTS SC448 LDX #$27 LOOP4 LDA SCREEN1+15*40,X STA SCREEN2+16*40,X LDA SCREEN1+14*40,X STA SCREEN2+15*40,X LDA SCREEN1+13*40,X STA SCREEN2+14*40,X DEX BPL LOOP4 RTS SC548 LDX #$27 LOOP5 LDA SCREEN1+12*40,X STA SCREEN2+13*40,X LDA SCREEN1+11*40,X STA SCREEN2+12*40,X LDA SCREEN1+10*40,X STA SCREEN2+11*40,X DEX BPL LOOP5 RTS SC648 LDX #$27 LOOP6 LDA SCREEN1+09*40,X STA SCREEN2+10*40,X LDA SCREEN1+08*40,X STA SCREEN2+09*40,X LDA SCREEN1+07*40,X STA SCREEN2+08*40,X DEX BPL LOOP6 RTS SC748 LDX #$27 LOOP7 LDA SCREEN1+06*40,X STA SCREEN2+07*40,X LDA SCREEN1+05*40,X STA SCREEN2+06*40,X LDA SCREEN1+04*40,X STA SCREEN2+05*40,X DEX BPL LOOP7 RTS SC848 LDX #$27 LOOP8 LDA SCREEN1+03*40,X STA SCREEN2+04*40,X LDA SCREEN1+02*40,X STA SCREEN2+03*40,X LDA SCREEN1+01*40,X STA SCREEN2+02*40,X LDA SCREEN1+00*40,X STA SCREEN2+01*40,X DEX BPL LOOP8 RTS SC14C LDX #$27 LOOP1A LDA SCREEN2+24*40,X STA SCREEN1+25*40,X LDA SCREEN2+23*40,X STA SCREEN1+24*40,X LDA SCREEN2+22*40,X STA SCREEN1+23*40,X DEX BPL LOOP1A RTS SC24C LDX #$27 LOOP2A LDA SCREEN2+21*40,X STA SCREEN1+22*40,X LDA SCREEN2+20*40,X STA SCREEN1+21*40,X LDA SCREEN2+19*40,X STA SCREEN1+20*40,X DEX BPL LOOP2A RTS SC34C LDX #$27 LOOP3A LDA SCREEN2+18*40,X STA SCREEN1+19*40,X LDA SCREEN2+17*40,X STA SCREEN1+18*40,X LDA SCREEN2+16*40,X STA SCREEN1+17*40,X DEX BPL LOOP3A RTS SC44C LDX #$27 LOOP4A LDA SCREEN2+15*40,X STA SCREEN1+16*40,X LDA SCREEN2+14*40,X STA SCREEN1+15*40,X LDA SCREEN2+13*40,X STA SCREEN1+14*40,X DEX BPL LOOP4A RTS SC54C LDX #$27 LOOP5A LDA SCREEN2+12*40,X STA SCREEN1+13*40,X LDA SCREEN2+11*40,X STA SCREEN1+12*40,X LDA SCREEN2+10*40,X STA SCREEN1+11*40,X DEX BPL LOOP5A RTS SC64C LDX #$27 LOOP6A LDA SCREEN2+09*40,X STA SCREEN1+10*40,X LDA SCREEN2+08*40,X STA SCREEN1+09*40,X LDA SCREEN2+07*40,X STA SCREEN1+08*40,X DEX BPL LOOP6A RTS SC74C LDX #$27 LOOP7A LDA SCREEN2+06*40,X STA SCREEN1+07*40,X LDA SCREEN2+05*40,X STA SCREEN1+06*40,X LDA SCREEN2+04*40,X STA SCREEN1+05*40,X DEX BPL LOOP7A RTS SC84C LDX #$27 LOOP8A LDA SCREEN2+03*40,X STA SCREEN1+04*40,X LDA SCREEN2+02*40,X STA SCREEN1+03*40,X LDA SCREEN2+01*40,X STA SCREEN1+02*40,X LDA SCREEN2+00*40,X STA SCREEN1+01*40,X DEX BPL LOOP8A RTS ; ; DUMP_SCREEN - Mauls the decode routine to print a big map section ; DUMP_SCREEN LDX #SCREEN1+24*40 LDY ^SCREEN1+24*40 STX BODGE_1+1 STY BODGE_1+2 LDX #$D800+24*40 LDY ^$D800+24*40 STX BODGE_COLOUR+1 STY BODGE_COLOUR+2 LDX #24 NEXT_LINE STX TEMPX JSR DODECODE LDA BODGE_1+1 SUB #40 STA BODGE_1+1 BCS SKPB_1 DEC BODGE_1+2 SKPB_1 LDA BODGE_COLOUR+1 SUB #40 STA BODGE_COLOUR+1 BCS SKPB_2 DEC BODGE_COLOUR+2 SKPB_2 LDX TEMPX DEX BNE NEXT_LINE LDX #SCREEN1 LDY ^SCREEN1 STX BODGE_1+1 STY BODGE_1+2 LDX #$D800 LDY ^$D800 STX BODGE_COLOUR+1 STY BODGE_COLOUR+2 RTS ; ; ADD_POINTS - Adds N number of points to player 1's score ; LDX #$10:LDY #$00 - Would add 1000 points to player 1's score ; then falls through and prints the score on the staus line ; ADD_POINTS SED TYA ADD PLRSC+2 STA PLRSC+2 TXA ADC PLRSC+1 STA PLRSC+1 LDA PLRSC ADC #0 STA PLRSC CLD RTS ; ; PRINT_SCORE - Prints player 1's score, ommitting any leading zeros ; PRINT_SCORE LDX #2 LDY #5 BUFFER_IT LDA PLRSC,X ; Expand score into buffer AND #$0F STA SC_BUFFER,Y DEY LDA PLRSC,X LSR LSR LSR LSR STA SC_BUFFER,Y DEY DEX BPL BUFFER_IT LDA #0 STA LEAD_FLAG TAX PRINT_UP LDA SC_BUFFER,X ; Print buffer ommiting leading zeros BNE NON_ZERO LDY LEAD_FLAG BEQ IGNORE_ZERO PRINT_SC ORA #$B0 STA SCREEN1+23*40+9,X STA SCREEN1+24*40+9,X STA SCREEN2+23*40+9,X STA SCREEN2+24*40+9,X IGNORE_ZERO INX CPX #6 BNE PRINT_UP RTS NON_ZERO INC LEAD_FLAG BNE PRINT_SC ; Always branch ! ; SC_BUFFER DFS 6,0 ; Score decode buffer LEAD_FLAG DFB 0 ; Leading zero indicator flag ; ; ; DECODE - Decode the map to the top line of the current screen ; DECODE LDA DECODEFLAG ; Should a decode take place BNE DODECODE RTS DODECODE LDA #0 STA DECODEFLAG INC MAPCOUNT ; Increment map baddy location BNE NOHIGH INC MAPCOUNT+1 NOHIGH LDA VERPOS ; Decrement map counter SUB #1 STA VERPOS BCS NOHIGH2 DEC VERPOS+1 NOHIGH2 STA MAP ; Map location DIV 4 LDA VERPOS+1 LSR ROR MAP LSR ROR MAP STA MAP+1 LDA MAP ; Plus base address of the map ADD #MAPSTART STA MAP LDA MAP+1 ADC ^MAPSTART STA MAP+1 LDA VERPOS ; Vertical depth within the block AND #3 ASL ASL STA BLOCKINDEX LDX #0 NEXTBLOCK LDY #0 STY COUNT STY BLOCK+1 LDA (MAP),Y ASL:ROL BLOCK+1 ; Block number * 16 ASL:ROL BLOCK+1 ASL:ROL BLOCK+1 ASL:ROL BLOCK+1 ADD #BLOCKSTART ; Plus block base address STA BLOCK LDA BLOCK+1 ADC ^BLOCKSTART STA BLOCK+1 LDY BLOCKINDEX ; Index vertical depth within block PRINT LDA (BLOCK),Y BODGE_1 STA SCREEN1,X ; Print on both screens STA SCREEN2,X STY TEMP TAY LDA ATTR,Y ; Get the attribute for that char BODGE_COLOUR STA $D800,X LDY TEMP INY INX CPX #40 BEQ DONEDECODE ; Finished a line ? INC COUNT LDA COUNT ; Finished decoding a block ? CMP #4 BNE PRINT LDA MAP ; Add map height to map address ADD #MAPH STA MAP BCC NEXTBLOCK INC MAP+1 JMP NEXTBLOCK ; Work out the next block DONEDECODE RTS ; ; COLOUR_SCROLL - Block scroll the colour ram down one line ; COLOUR_SCROLL LDA COLOURFLAG ; Colour scroll required ? BNE DOCOL RTS DOCOL LDY #39 COLLOOP1 LDA $DA08,Y:STA COLBUF,Y ; Buffer middle line LDA $D9E0,Y:STA $DA08,Y LDA $D9B8,Y:STA $D9E0,Y LDA $D990,Y:STA $D9B8,Y LDA $D968,Y:STA $D990,Y LDA $D940,Y:STA $D968,Y LDA $D918,Y:STA $D940,Y LDA $D8F0,Y:STA $D918,Y LDA $D8C8,Y:STA $D8F0,Y LDA $D8A0,Y:STA $D8C8,Y LDA $D878,Y:STA $D8A0,Y LDA $D850,Y:STA $D878,Y LDA $D828,Y:STA $D850,Y LDA $D800,Y:STA $D828,Y DEY BPL COLLOOP1 LDY #39 COLLOOP2 LDA $DB98,Y:STA $DBC0,Y LDA $DB70,Y:STA $DB98,Y LDA $DB48,Y:STA $DB70,Y LDA $DB20,Y:STA $DB48,Y LDA $DAF8,Y:STA $DB20,Y LDA $DAD0,Y:STA $DAF8,Y LDA $DAA8,Y:STA $DAD0,Y LDA $DA80,Y:STA $DAA8,Y LDA $DA58,Y:STA $DA80,Y LDA $DA30,Y:STA $DA58,Y LDA COLBUF,Y:STA $DA30,Y DEY BPL COLLOOP2 LDA #0 STA COLOURFLAG RTS ; ; GAME_SETUP - Initialises any tables and non-zero variables ; GAME_SETUP LDA #BADDYDATA ; Initialise attack path Database STA DATABASE LDA ^BADDYDATA STA DATABASE+1 LDA #STARTPOS ; Initialise map start location STA VERPOS LDA ^STARTPOS STA VERPOS+1 LDX #2 ; Set half pixel scroll counter STX HALFPIX STX LIVES LDX #MGREY ; Initial sprite multicolour 1 STX $D025 LDX #LGREY STX $D026 ; Initial sprite multicolour 2 LDX #$0B STX $D022 ; Initial character multi colour 1 INX STX $D023 ; Initial character multi colour 2 LDA #YELLOW ; Player's ship colours STA SPRC LDA #RED STA SPRC+1 STA SPRC+2 LDA #86 ; Initialise player's X & Y STA SX LDA #80 STA SX+1 LDA #92 STA SX+2 LDA #204 STA SY ADD #17 ; Underside of player's ship STA SY+1 STA SY+2 LDX #$40 ; Sprite pointers for ship STX SPRCHR INX STX SPRCHR+1 INX STX SPRCHR+2 RTS ; ; HIT_BADDIES - Procceses collision detection between bullets and baddies ; HIT_BADDIES LDA WEAPON ASL TAX LDA COLLIS_ROUTS,X STA COLLIS_MOD_1+1 LDA COLLIS_ROUTS+1,X STA COLLIS_MOD_1+2 COLLIS_MOD_1 JMP $FFFF ; Self modified ;-------------- COLLIS_ROUTS DFW PULSE_COLLIS DFW LASER_COLLIS DFW NANA_COLLIS DFW LASER_COLLIS ; ?????????????? ;-------------- ; ; PULSE_COLLIS - For collision detection between pulse lase and baddies ; PULSE_COLLIS LDY #3 ; 4 player bullets in total NEXT_BULLET LDX #ALIENS-1 SEARCH_BADDY LDA ALIENON,X BNE ALIEN_IS_ON DEX BPL SEARCH_BADDY DEY BPL NEXT_BULLET RTS ALIEN_IS_ON LDA EXPLODE_FLAGS,X ; Is the alien already exploding ? BEQ NOT_ALREADY DEX BPL SEARCH_BADDY DEY BPL NEXT_BULLET RTS NOT_ALREADY LDA FIREFLAG,Y ; Has this bullet been fired ? BNE IS_FIRING DEX BPL SEARCH_BADDY DEY BPL NEXT_BULLET RTS IS_FIRING LDA SY+4,X ; Target sprite SUB #21 ; Object height CMP SY+22,Y ; Object sprite BCS NO_HIT ADC #42 ; Object height + target height CMP SY+22,Y ; Object sprite BCC NO_HIT LDA SX+4,X ; Target sprite SUB #10 ; Object width DIV 2 CMP SX+22,Y ; Object sprite BCS NO_HIT ADC #20 ; Object width + target width DIV 2 CMP SX+22,Y ; Object sprite BCC NO_HIT LDA DESTROYSHOTS,X ; Alien been hit enough ? BEQ CAN_DIE DEC DESTROYSHOTS,X ; No, JMP CANCEL_BULLET ; but stop player bullet CAN_DIE LDA #1 ; Yes STA EXPLODE_FLAGS,X ; Trigger explosion LDA #YELLOW STA SPRC+4,X LDA #$60 ; First frame of explosion STA SPRCHR+4,X CANCEL_BULLET LDA #0 STA BANG_TIME,X ; Init delay time between frames STA FIREFLAG,Y ; Shut down player bullet STA SX+22,Y STA SY+22,Y NO_HIT DEX BPL SEARCH_BADDY DEY BPL NEXT_BULLET RTS ; ; LASER_COLLIS - For collision between laser and baddies ; LASER_COLLIS RTS ; ; NANA_COLLIS - For collision betwwen big bananna and baddies ! ; NANA_COLLIS LDA FIREFLAG BNE IS_FIRE_1 RTS IS_FIRE_1 LDX #ALIENS-1 NANA_SEARCH LDA ALIENON,X BNE ALIEN_ON_1 DEX BPL NANA_SEARCH RTS ALIEN_ON_1 LDA EXPLODE_FLAGS,X ; Is the alien already exploding ? BEQ NOT_EXPL_1 DEX BPL NANA_SEARCH RTS NOT_EXPL_1 LDA SY+4,X ; Target sprite SUB #21 ; Object height CMP SY+22 ; Object sprite BCS NO_HIT_1 ADC #42 ; Object height + target height CMP SY+22 ; Object sprite BCC NO_HIT_1 LDA SX+4,X ; Target sprite SUB #[24*3]/2 ; Object width DIV 2 CMP SX+22 ; Object sprite BCS NO_HIT_1 ADC #[24*3+24]/2 ; Object width + target width DIV 2 CMP SX+22 ; Object sprite BCC NO_HIT_1 LDA #1 ; The nana weapon wipes anything STA EXPLODE_FLAGS,X ; in its path so DESTRYSHOTS don't LDA #YELLOW ; count. STA SPRC+4,X LDA #$60 ; First frame of explosion STA SPRCHR+4,X LDA #0 STA BANG_TIME,X ; Init delay time between frames STA FIREFLAG ; Shut down nana STA FIREFLAG+1 STA FIREFLAG+2 STA SX+22 STA SX+23 STA SX+24 STA SY+22 STA SY+23 STA SY+24 NO_HIT_1 DEX BPL NANA_SEARCH RTS ; ; EXPLODE_BADDY - Proccesses explosion animation for the baddies ; EXPLODE_BADDY LDX #ALIENS-1 SEARCH_ON LDA ALIENON,X ; Alien on ? BNE TRY_FLAGS DEX BPL SEARCH_ON RTS TRY_FLAGS LDA EXPLODE_FLAGS,X ; Yes, is it exploding ? BNE IS_EXPLODING DEX BPL SEARCH_ON RTS IS_EXPLODING LDA BANG_TIME,X ; Delay between frames ADD #1 AND #3 STA BANG_TIME,X BEQ NEXT_BOOM DEX BPL SEARCH_ON RTS NEXT_BOOM LDA SPRCHR+4,X ; Last frame of animation reached ? CMP #$64 BEQ EXPLODE_OVER INC SPRCHR+4,X ; No, do next frame DEX BPL SEARCH_ON RTS EXPLODE_OVER LDA LEAVE_FLAGS,X ; Should we leave anything behind BEQ NO_LEAVE STA LOCKON+27 ; Yes LDA SX+4,X STA SX+27 LDA SY+4,X STA SY+27 LDA #BLUE STA SPRC+27 LDA #$65 STA SPRCHR+27 NO_LEAVE LDA #0 ; Explosion complete STA SX+4,X STA SY+4,X STA ALIENON,X STA EXPLODE_FLAGS,X STA LEAVE_FLAGS,X DEX BPL SEARCH_ON RTS ; ; CHANGE_WEAPON - Changes processing to a new weapon ir requested ; CHANGE_WEAPON LDA WEAPON_PENDING ; Is there a new weapon waiting to BNE IS_PENDING ; be set up ? RTS ; No IS_PENDING LDA FIREFLAG ORA FIREFLAG+1 ORA FIREFLAG+2 ORA FIREFLAG+3 BEQ OK_CHANGE RTS OK_CHANGE DEC WEAPON_PENDING ; Shut flag down LDA NEW_WEAPON STA WEAPON RTS ; ; COLLECT_ICON - Picks up any power up thingys ! ; COLLECT_ICON LDX #3 SCAN_LOCKS LDA LOCKON+27,X BNE IS_LOCKED DEX BPL SCAN_LOCKS RTS IS_LOCKED LDA SY+27,X ; Target sprite SUB #21 ; Object height CMP SY ; Object sprite BCS NOT_GOT ADC #42 ; Object height + target height CMP SY ; Object sprite BCC NOT_GOT LDA SX+27,X ; Target sprite SUB #10 ; Object width DIV 2 CMP SX ; Object sprite BCS NOT_GOT ADC #20 ; Object width + target width DIV 2 CMP SX ; Object sprite BCC NOT_GOT LDA #0 ; Cancel power-up icon STA LOCKON+27,X STA SX+27,X STA SY+27,X LDY WEAPON ; Just to test CPY #2 BNE NO_RESET LDY #$FF NO_RESET INY STY NEW_WEAPON LDA #1 STA WEAPON_PENDING NOT_GOT DEX BPL SCAN_LOCKS RTS ; ; JOY - Interpret players joystick movements ; JOY LDA $DC00 AND #$1F EOR #$1F STA JOYTEMP AND #$0F ASL TAX LDA JOYACTION+0,X STA JOYJUMP+1 LDA JOYACTION+1,X STA JOYJUMP+2 JOYJUMP JMP $AAAA ; Self modified JOYACTION DFW NOWT DFW up DFW down DFW NOWT DFW LEFT DFW UL DFW DL DFW NOWT DFW RIGHT DFW UR DFW DR DFW NOWT DFW NOWT DFW NOWT DFW NOWT DFW NOWT NOWT RTS ; Do nothing ... exit UL JSR up JMP LEFT DL JSR down JMP LEFT UR JSR up JMP RIGHT DR JSR down JMP RIGHT ; up LDA SY CMP #53 BCC NO1 SUB #2 STA SY LDA SY+1 SUB #2 STA SY+1 STA SY+2 LDA LASER_ON BEQ NO1 LDX #3 SHIFT_UP LDA SY+22,X SUB #2 STA SY+22,X DEX BPL SHIFT_UP NO1 RTS ; down LDA SY CMP #225-21 BCS NO2 ADD #2 STA SY LDA SY+1 ADD #2 STA SY+1 STA SY+2 LDA LASER_ON BEQ NO2 LDX #3 SHIFT_DOWN LDA SY+22,X ADD #2 STA SY+22,X DEX BPL SHIFT_DOWN NO2 RTS ; LEFT LDA SX CMP #18 BCC NO3 SUB #1 STA SX LDA SX+1 SUB #1 STA SX+1 LDA SX+2 SUB #1 STA SX+2 LDA LASER_ON BEQ NO3 LDX #3 SHIFT_LEFT LDA SX+22,X SUB #1 STA SX+22,X DEX BPL SHIFT_LEFT NO3 RTS ; RIGHT LDA SX CMP #154 BCS NO4 ADD #1 STA SX LDA SX+1 ADD #1 STA SX+1 LDA SX+2 ADD #1 STA SX+2 LDA LASER_ON BEQ NO4 LDX #3 SHIFT_RIGHT LDA SX+22,X ADD #1 STA SX+22,X DEX BPL SHIFT_RIGHT NO4 RTS ; ; DOBULLETS - Processes and moves player bullets ; DOBULLETS LDA JOYTEMP ; Bit 4 set AND #$10 BNE FIREPRESS JMP MOVEMYBUL ; No, move any active bullets FIREPRESS LDA WEAPON ; Initialise the current weapon ASL TAX LDA WEAPON_INITS,X STA JUMP_MOD_1+1 LDA WEAPON_INITS+1,X STA JUMP_MOD_1+2 JUMP_MOD_1 JMP $FFFF ;----------------------------------------------------------------------------- ;Weapon control tables WEAPON_INITS DFW INIT_BULLET DFW INIT_LASER DFW INIT_BIG_NANA DFW INIT_4WAY WEAPON_ROUTS DFW MOVE_BULLET DFW MOVE_LASER DFW MOVE_BIG_NANA DFW MOVE_4WAY ;----------------------------------------------------------------------------- MOVEMYBUL LDA FIREFLAG ; Check if we are firing ORA FIREFLAG+1 ORA FIREFLAG+2 ORA FIREFLAG+3 BNE IS_FIRE RTS IS_FIRE LDA WEAPON ; Process the current weapon ASL TAX LDA WEAPON_ROUTS,X STA JUMP_MOD_2+1 LDA WEAPON_ROUTS+1,X STA JUMP_MOD_2+2 JUMP_MOD_2 JMP $FFFF ; ; INIT_BULLET - Initialises the "pulse" laser ; INIT_BULLET LDA FIREFLAG BEQ INIT_PULSE JMP MOVEMYBUL INIT_PULSE INC FIREFLAG ; Bullet sprite 1 is firing LDA SX ; Set up a bullet STA SX+22 LDA SY SUB #14 STA SY+22 LDA #1 STA SPRC+22 LDA #$49 STA SPRCHR+22 RTS ; ; INIT_LASER - Initialises the "defender" laser ; INIT_LASER LDA FIREFLAG BEQ INIT_LAS JMP MOVEMYBUL INIT_LAS INC FIREFLAG ; 4 bullet sprites active ; INC FIREFLAG+1 ; INC FIREFLAG+2 ; INC FIREFLAG+3 ; LDA SX STA SX+22 STA SX+23 STA SX+24 STA SX+25 LDA SY SUB #16 STA SY+22 SBC #21 STA SY+23 SBC #21 STA SY+24 SBC #21 STA SY+25 LDA #YELLOW STA SPRC+22 STA SPRC+23 STA SPRC+24 STA SPRC+25 LDA #$52 STA SPRCHR+22 STA SPRCHR+23 STA SPRCHR+24 STA SPRCHR+25 LDX #0 STX LASER_LENGTH INX STX LASER_ON ; Indicate the laser is active RTS ; ; INIT_4WAY - Initialises the 4 way blaster ; INIT_4WAY LDA FIREFLAG ORA FIREFLAG+1 ORA FIREFLAG+2 ORA FIREFLAG+3 BEQ OK_INIT4WAY JMP MOVEMYBUL OK_INIT4WAY INC FIREFLAG INC FIREFLAG+1 INC FIREFLAG+2 INC FIREFLAG+3 LDA SY SUB #12 STA SY+22 ; Top left arc STA SY+23 ; Top right arc ADD #36 STA SY+24 ; Bottom left arc STA SY+25 ; Bottom right arc LDA SX SUB #12 STA SX+22 STA SX+24 ADD #24 STA SX+23 STA SX+25 LDA #ORANGE ; Arc colours STA SPRC+22 STA SPRC+23 STA SPRC+24 STA SPRC+25 LDX #$7D ; Arc contiguosly running pointers STX SPRCHR+22 INX STX SPRCHR+23 INX STX SPRCHR+24 INX STX SPRCHR+25 RTS ; ; INIT_BIG_NANA - Initialises the big bannana weapon ! ; INIT_BIG_NANA LDA FIREFLAG BEQ OK_INIT JMP MOVEMYBUL OK_INIT INC FIREFLAG ; 3 bullet sprites active INC FIREFLAG+1 INC FIREFLAG+2 LDA SY SUB #5 STA SY+22 ; Init bannana Y coords STA SY+23 STA SY+24 LDA SX STA SX+23 ; Bannana centre SUB #12 STA SX+22 ; Bannana left ADD #24 STA SX+24 ; Bannana right LDA #YELLOW ; Bannana colour STA SPRC+22 STA SPRC+23 STA SPRC+24 LDX #$4D STX SPRCHR+22 ; Bannana pointers INX STX SPRCHR+24 INX STX SPRCHR+23 RTS ; ; MOVE_BULLET - Moves a single "pulse" laser ; MOVE_BULLET LDA SY+22 ; Yes, move players bullet SUB #6 STA SY+22 CMP #$28 BCC TURNBULOFF RTS TURNBULOFF LDA #0 ; Switch player bullet off STA SY+22 STA SX+22 STA FIREFLAG RTS ; ; MOVE_4WAY - Moves the 4 way arc ; MOVE_4WAY LDX #3 MOVE_ARC LDA FIREFLAG,X BNE DO_THIS DEX BPL MOVE_ARC RTS DO_THIS LDA SY+22,X ADD Y_OFFSET,X CMP #$28 ; Minimum Y value BCC TURN_ME_OFF CMP #250 ; Maximum Y value BCS TURN_ME_OFF STA SY+22,X LDA SX+22,X ADD X_OFFSET,X CMP #5 ; Minimum X value BCC TURN_ME_OFF CMP #165 ; Maximum X value BCS TURN_ME_OFF STA SX+22,X DEX BPL MOVE_ARC RTS TURN_ME_OFF LDA #0 STA FIREFLAG,X STA SX+22,X STA SY+22,X DEX BPL MOVE_ARC RTS ; X_OFFSET DFL -2,2,-2,2 Y_OFFSET DFL -3,-3,3,3 ; ; ; MOVE_LASER - Moves the mega big laser ; MOVE_LASER LDY LASER_LENGTH CPY #28*2 BEQ FULL_LENGTH LDX POINTER_SPRITE,Y LDA LASER_POINTER,Y STA SPRCHR+22,X INC LASER_LENGTH RTS FULL_LENGTH LDA #0 STA SX+22 STA SX+23 STA SX+24 STA SX+25 STA SY+22 STA SY+23 STA SY+24 STA SY+25 STA LASER_ON STA FIREFLAG RTS ; POINTER_SPRITE DFB 0,0,0,0,0,0,0 DFB 1,1,1,1,1,1,1 DFB 2,2,2,2,2,2,2 DFB 3,3,3,3,3,3,3 DFB 0,0,0,0,0,0,0 DFB 1,1,1,1,1,1,1 DFB 2,2,2,2,2,2,2 DFB 3,3,3,3,3,3,3 ; LASER_POINTER DFB $53,$54,$55,$56,$57,$58,$59 DFB $53,$54,$55,$56,$57,$58,$59 DFB $53,$54,$55,$56,$57,$58,$59 DFB $53,$54,$55,$56,$57,$58,$59 DFB $5A,$5B,$5C,$5D,$5E,$5F,$52 DFB $5A,$5B,$5C,$5D,$5E,$5F,$52 DFB $5A,$5B,$5C,$5D,$5E,$5F,$52 DFB $5A,$5B,$5C,$5D,$5E,$5F,$52 ; ; MOVE_BIG_NANA - Moves the big bannana weapon ! ; MOVE_BIG_NANA LDA SY+22 CMP #$28 BCC BIG_NANA_OFF SUB #5 STA SY+22 STA SY+23 STA SY+24 RTS BIG_NANA_OFF LDA #0 STA SY+22 STA SY+23 STA SY+24 STA FIREFLAG RTS ; ; SETBANK - Initialises video base address ; SETBANK LDA #$C0 ; Bank 3 ($C000) STA $DD00 LDA #$10 ; Charset @ $C000 STA $D018 LDA #32 ; Video base @ $C800 STA SCRBASE RTS ; ; CLS - Clears out both play screens and clears up the attributes ; CLS LDX #0 STX $D020 STX $D021 CLR LDA #$20 STA $C800,X ; Screen A STA $C900,X STA $CA00,X STA $CB00,X STA $CC00,X ; Screen B STA $CD00,X STA $CE00,X STA $CF00,X STA $D800,X ; Colour RAM STA $D900,X STA $DA00,X STA $DB00,X INX BNE CLR RTS ; ; GRAB_CHARS - Grabs the required char set for the game ; GRAB_CHARS LDX #0 COPY_SET LDA $6000,X STA $C000,X LDA $6100,X STA $C100,X LDA $6200,X STA $C200,X LDA $6300,X STA $C300,X LDA $6400,X STA $C400,X LDA $6500,X STA $C500,X LDA $6600,X STA $C600,X LDA $6700,X STA $C700,X INX BNE COPY_SET RTS ; ; SET_READY - Initialises the "GET READY" sprites ; SET_READY LDA #1 STA READY_ON LDA #BLUE STA SPRC+27 STA SPRC+28 STA SPRC+29 LDX #$68 STX SPRCHR+27 INX STX SPRCHR+28 INX STX SPRCHR+29 LDA #$A0 STA SY+27 STA SY+28 STA SY+29 LDA #71 STA SX+27 ADD #12 STA SX+28 ADC #12 STA SX+29 LDA #200 STA READY_TIMER RTS ; ; PROCESS_READY - Displays "GET READY" if it is required ; PROCESS_READY LDA READY_ON BNE DO_READY RTS DO_READY DEC READY_TIMER BEQ READY_OVER RTS READY_OVER DEC READY_ON LDA #0 STA SX+27 STA SX+28 STA SX+29 STA SY+27 STA SY+28 STA SY+29 RTS ; ; SETUP - Initialises the multiplexor ; SETUP LDY #NSP-1 SET1 TYA STA PNT1,Y ; Clear pointers in decending order LDA #0 STA SX,Y ; Clear multiplexor variables STA SX_BUFFER,Y STA SY,Y STA SY_BUFFER,Y STA SPRC,Y AND #$0F TAX LDA #0 STA $D000,X ; and VIC variables DEY BPL SET1 STY $D015 ; Sprites on STY $D01C ; Multi colour enable INY STY $D010 ; MSB clear LDA #32 ; Screen @ $C800 STA SCRBASE LDA $D011 ; Screen enabled AND #$F7 STA $D011 LDA #$D8 ; Reset screen X STA $D016 JMP GENLIST ; Generate sprite order list ; ; CLRVARS - Resets any variables that need reseting to zero ; CLRVARS LDA #VSTART STA TO LDA ^VSTART STA TO+1 LDY #0 CLRLOOP LDA #0 STA (TO),Y INC TO BNE NOC INC TO+1 NOC LDA TO CMP #VEND BNE CLRLOOP LDA TO+1 CMP ^VEND BNE CLRLOOP RTS ; LDA #$50 ; Crash VIC chip to blank scroll line ; STA $D011 ; LDA $D011 ; Uncrash the VIC chip ; AND #$3F ; STA $D011 ; ; R0 - Second raster, base of the screen ; Handles Scroll & multiplexor sort ; R0 STA IA STX IX STY IY CLD DEC $D019 LDA #$3800 ; Set NMI to count to middle of screen STA $DD04 LDA ^$3800 STA $DD05 LDA #%10011001 STA $DD0E IF SHOW_RASTER=TRUE LDA #6 STA $D020 ELSE JSR SMOOTH ; Process the hardware scroll LDA $D011 AND #$F8 ORA POS STA $D011 ; Pass on to the hardware JSR SCROLL ; Do the scroll block transfer IF SHOW_RASTER=TRUE LDA #0 STA $D020 ELSE LDA $D018 ; Point to the fully updated screen AND #$0F ORA SCRBASE STA $D018 IF SHOW_RASTER=TRUE LDA #2 STA $D020 ELSE JSR GENLIST ; Generate the multiplexor sprite list JSR CLRVIC ; Clear out the VIC chip INC LASTCOUNT LDA COLOURFLAG ; If a colour scroll takes place this BNE NOSYNC ; cycle don't sync the main loop INC DELAYFLAG NOSYNC IF SHOW_RASTER=TRUE LDA #0 STA $D020 ELSE LDA #PLEX STA $FFFE LDA ^PLEX STA $FFFF LDA #$20 STA $D012 LDA IA LDX IX LDY IY RTI ; ; PLEX - Self generating raster dumps sprites onto the screen ; PLEX STA IA STX IX STY IY CLD DEC $D019 IF SHOW_RASTER=TRUE INC $D020 ELSE LDA $D012 ADD #RASTDIF ; Generate the maximum split time STA RASTEMP RAST3 LDX NXTSPR ; Which VIC sprite to use LDA SPRITE_TABLE_L,X STA SPRITE_JUMP+1 LDA SPRITE_TABLE_H,X ; Which routine to go to STA SPRITE_JUMP+2 SPRITE_JUMP JMP $FFFF ; Self modified sprite JUMP address ; SPRITE_1 LDY NXTSP ; Get the next multiplexed pointer LDX PNT1,Y LDA SY_BUFFER,X ; Multiplexor Y STA SPY ; VIC Y CMP RASTEMP BCS RASTEND_1 ; Over the maximum time ... Exit LDA SX_BUFFER,X ASL STA SPX ; Put the X into the VIC chip LDA SPRC,X ; Put the colour into the VIC chip STA SPC LDA SPRCHR,X ; and the pointers STA $CBF8 STA $CFF8 BCC MASKMSB_1 SETMSB_1 LDA $D010 ; Set the MSB ORA #1 STA $D010 BNE NEXTSPRITE_1 ; Always MASKMSB_1 LDA $D010 ; Clear the MSB AND #$FE STA $D010 NEXTSPRITE_1 DEC NXTSP ; Do the next multiplexed sprite BMI DONEALL_1 DEC NXTSPR ; And the next VIC sprite BMI RESET_1 JMP RAST3 RESET_1 LDA #7 ; Reset the VIC sprite number STA NXTSPR JMP RAST3 DONEALL_1 LDA #7 STA NXTSPR LDA #$F0 ; Next raster position STA $D012 LDA #R0 STA $FFFE LDA ^R0 STA $FFFF JMP OUT1_1 RASTEND_1 SBC #RASTDIF ; Work out the next split position CMP $D012 BEQ XIT1_1 BCS XIT2_1 LDA $D012 XIT1_1 ADD #2 XIT2_1 ADC #1 STA $D012 OUT1_1 IF SHOW_RASTER=TRUE DEC $D020 ELSE LDA IA LDX IX LDY IY RTI ; SPRITE_2 LDY NXTSP ; Get the next multiplexed pointer LDX PNT1,Y LDA SY_BUFFER,X ; Multiplexor Y STA SPY+2 ; VIC Y CMP RASTEMP BCS RASTEND_2 ; Over the maximum time ... Exit LDA SX_BUFFER,X ASL STA SPX+2 ; Put the X into the VIC chip LDA SPRC,X ; Put the colour into the VIC chip STA SPC+1 LDA SPRCHR,X ; and the pointers STA $CBF9 STA $CFF9 BCC MASKMSB_2 SETMSB_2 LDA $D010 ; Set the MSB ORA #2 STA $D010 BNE NEXTSPRITE_2 ; Always MASKMSB_2 LDA $D010 ; Clear the MSB AND #$FD STA $D010 NEXTSPRITE_2 DEC NXTSP ; Do the next multiplexed sprite BMI DONEALL_2 DEC NXTSPR ; And the next VIC sprite BMI RESET_2 JMP RAST3 RESET_2 LDA #7 ; Reset the VIC sprite number STA NXTSPR JMP RAST3 DONEALL_2 LDA #7 STA NXTSPR LDA #$F0 ; Next raster position STA $D012 LDA #R0 STA $FFFE LDA ^R0 STA $FFFF JMP OUT1_2 RASTEND_2 SBC #RASTDIF ; Work out the next split position CMP $D012 BEQ XIT1_2 BCS XIT2_2 LDA $D012 XIT1_2 ADD #2 XIT2_2 ADC #1 STA $D012 OUT1_2 IF SHOW_RASTER=TRUE DEC $D020 ELSE LDA IA LDX IX LDY IY RTI ; SPRITE_3 LDY NXTSP ; Get the next multiplexed pointer LDX PNT1,Y LDA SY_BUFFER,X ; Multiplexor Y STA SPY+4 ; VIC Y CMP RASTEMP BCS RASTEND_3 ; Over the maximum time ... Exit LDA SX_BUFFER,X ASL STA SPX+4 ; Put the X into the VIC chip LDA SPRC,X ; Put the colour into the VIC chip STA SPC+2 LDA SPRCHR,X ; and the pointers STA $CBFA STA $CFFA BCC MASKMSB_3 SETMSB_3 LDA $D010 ; Set the MSB ORA #4 STA $D010 BNE NEXTSPRITE_3 ; Always MASKMSB_3 LDA $D010 ; Clear the MSB AND #$FB STA $D010 NEXTSPRITE_3 DEC NXTSP ; Do the next multiplexed sprite BMI DONEALL_3 DEC NXTSPR ; And the next VIC sprite BMI RESET_3 JMP RAST3 RESET_3 LDA #7 ; Reset the VIC sprite number STA NXTSPR JMP RAST3 DONEALL_3 LDA #7 STA NXTSPR LDA #$F0 ; Next raster position STA $D012 LDA #R0 STA $FFFE LDA ^R0 STA $FFFF JMP OUT1_2 RASTEND_3 SBC #RASTDIF ; Work out the next split position CMP $D012 BEQ XIT1_3 BCS XIT2_3 LDA $D012 XIT1_3 ADD #2 XIT2_3 ADC #1 STA $D012 OUT1_3 IF SHOW_RASTER=TRUE DEC $D020 ELSE LDA IA LDX IX LDY IY RTI ; SPRITE_4 LDY NXTSP ; Get the next multiplexed pointer LDX PNT1,Y LDA SY_BUFFER,X ; Multiplexor Y STA SPY+6 ; VIC Y CMP RASTEMP BCS RASTEND_4 ; Over the maximum time ... Exit LDA SX_BUFFER,X ASL STA SPX+6 ; Put the X into the VIC chip LDA SPRC,X ; Put the colour into the VIC chip STA SPC+3 LDA SPRCHR,X ; and the pointers STA $CBFB STA $CFFB BCC MASKMSB_4 SETMSB_4 LDA $D010 ; Set the MSB ORA #8 STA $D010 BNE NEXTSPRITE_4 ; Always MASKMSB_4 LDA $D010 ; Clear the MSB AND #$F7 STA $D010 NEXTSPRITE_4 DEC NXTSP ; Do the next multiplexed sprite BMI DONEALL_4 DEC NXTSPR ; And the next VIC sprite BMI RESET_4 JMP RAST3 RESET_4 LDA #7 ; Reset the VIC sprite number STA NXTSPR JMP RAST3 DONEALL_4 LDA #7 STA NXTSPR LDA #$F0 ; Next raster position STA $D012 LDA #R0 STA $FFFE LDA ^R0 STA $FFFF JMP OUT1_4 RASTEND_4 SBC #RASTDIF ; Work out the next split position CMP $D012 BEQ XIT1_4 BCS XIT2_4 LDA $D012 XIT1_4 ADD #2 XIT2_4 ADC #1 STA $D012 OUT1_4 IF SHOW_RASTER=TRUE DEC $D020 ELSE LDA IA LDX IX LDY IY RTI ; SPRITE_5 LDY NXTSP ; Get the next multiplexed pointer LDX PNT1,Y LDA SY_BUFFER,X ; Multiplexor Y STA SPY+8 ; VIC Y CMP RASTEMP BCS RASTEND_5 ; Over the maximum time ... Exit LDA SX_BUFFER,X ASL STA SPX+8 ; Put the X into the VIC chip LDA SPRC,X ; Put the colour into the VIC chip STA SPC+4 LDA SPRCHR,X ; and the pointers STA $CBFC STA $CFFC BCC MASKMSB_5 SETMSB_5 LDA $D010 ; Set the MSB ORA #16 STA $D010 BNE NEXTSPRITE_5 ; Always MASKMSB_5 LDA $D010 ; Clear the MSB AND #$EF STA $D010 NEXTSPRITE_5 DEC NXTSP ; Do the next multiplexed sprite BMI DONEALL_5 DEC NXTSPR ; And the next VIC sprite BMI RESET_5 JMP RAST3 RESET_5 LDA #7 ; Reset the VIC sprite number STA NXTSPR JMP RAST3 DONEALL_5 LDA #7 STA NXTSPR LDA #$F0 ; Next raster position STA $D012 LDA #R0 STA $FFFE LDA ^R0 STA $FFFF JMP OUT1_2 RASTEND_5 SBC #RASTDIF ; Work out the next split position CMP $D012 BEQ XIT1_5 BCS XIT2_5 LDA $D012 XIT1_5 ADD #2 XIT2_5 ADC #1 STA $D012 OUT1_5 IF SHOW_RASTER=TRUE DEC $D020 ELSE LDA IA LDX IX LDY IY RTI ; SPRITE_6 LDY NXTSP ; Get the next multiplexed pointer LDX PNT1,Y LDA SY_BUFFER,X ; Multiplexor Y STA SPY+10 ; VIC Y CMP RASTEMP BCS RASTEND_6 ; Over the maximum time ... Exit LDA SX_BUFFER,X ASL STA SPX+10 ; Put the X into the VIC chip LDA SPRC,X ; Put the colour into the VIC chip STA SPC+5 LDA SPRCHR,X ; and the pointers STA $CBFD STA $CFFD BCC MASKMSB_6 SETMSB_6 LDA $D010 ; Set the MSB ORA #32 STA $D010 BNE NEXTSPRITE_6 ; Always MASKMSB_6 LDA $D010 ; Clear the MSB AND #$DF STA $D010 NEXTSPRITE_6 DEC NXTSP ; Do the next multiplexed sprite BMI DONEALL_6 DEC NXTSPR ; And the next VIC sprite BMI RESET_6 JMP RAST3 RESET_6 LDA #7 ; Reset the VIC sprite number STA NXTSPR JMP RAST3 DONEALL_6 LDA #7 STA NXTSPR LDA #$F0 ; Next raster position STA $D012 LDA #R0 STA $FFFE LDA ^R0 STA $FFFF JMP OUT1_2 RASTEND_6 SBC #RASTDIF ; Work out the next split position CMP $D012 BEQ XIT1_6 BCS XIT2_6 LDA $D012 XIT1_6 ADD #2 XIT2_6 ADC #1 STA $D012 OUT1_6 IF SHOW_RASTER=TRUE DEC $D020 ELSE LDA IA LDX IX LDY IY RTI ; SPRITE_7 LDY NXTSP ; Get the next multiplexed pointer LDX PNT1,Y LDA SY_BUFFER,X ; Multiplexor Y STA SPY+12 ; VIC Y CMP RASTEMP BCS RASTEND_7 ; Over the maximum time ... Exit LDA SX_BUFFER,X ASL STA SPX+12 ; Put the X into the VIC chip LDA SPRC,X ; Put the colour into the VIC chip STA SPC+6 LDA SPRCHR,X ; and the pointers STA $CBFE STA $CFFE BCC MASKMSB_7 SETMSB_7 LDA $D010 ; Set the MSB ORA #64 STA $D010 BNE NEXTSPRITE_7 ; Always MASKMSB_7 LDA $D010 ; Clear the MSB AND #$BF STA $D010 NEXTSPRITE_7 DEC NXTSP ; Do the next multiplexed sprite BMI DONEALL_7 DEC NXTSPR ; And the next VIC sprite BMI RESET_7 JMP RAST3 RESET_7 LDA #7 ; Reset the VIC sprite number STA NXTSPR JMP RAST3 DONEALL_7 LDA #7 STA NXTSPR LDA #$F0 ; Next raster position STA $D012 LDA #R0 STA $FFFE LDA ^R0 STA $FFFF JMP OUT1_7 RASTEND_7 SBC #RASTDIF ; Work out the next split position CMP $D012 BEQ XIT1_7 BCS XIT2_7 LDA $D012 XIT1_7 ADD #2 XIT2_7 ADC #1 STA $D012 OUT1_7 IF SHOW_RASTER=TRUE DEC $D020 ELSE LDA IA LDX IX LDY IY RTI ; SPRITE_8 LDY NXTSP ; Get the next multiplexed pointer LDX PNT1,Y LDA SY_BUFFER,X ; Multiplexor Y STA SPY+14 ; VIC Y CMP RASTEMP BCS RASTEND_8 ; Over the maximum time ... Exit LDA SX_BUFFER,X ASL STA SPX+14 ; Put the X into the VIC chip LDA SPRC,X ; Put the colour into the VIC chip STA SPC+7 LDA SPRCHR,X ; and the pointers STA $CBFF STA $CFFF BCC MASKMSB_8 SETMSB_8 LDA $D010 ; Set the MSB ORA #128 STA $D010 BNE NEXTSPRITE_8 ; Always MASKMSB_8 LDA $D010 ; Clear the MSB AND #$7F STA $D010 NEXTSPRITE_8 DEC NXTSP ; Do the next multiplexed sprite BMI DONEALL_8 DEC NXTSPR ; And the next VIC sprite BMI RESET_8 JMP RAST3 RESET_8 LDA #7 ; Reset the VIC sprite number STA NXTSPR JMP RAST3 DONEALL_8 LDA #7 STA NXTSPR LDA #$F0 ; Next raster position STA $D012 LDA #R0 STA $FFFE LDA ^R0 STA $FFFF JMP OUT1_8 RASTEND_8 SBC #RASTDIF ; Work out the next split position CMP $D012 BEQ XIT1_8 BCS XIT2_8 LDA $D012 XIT1_8 ADD #2 XIT2_8 ADC #1 STA $D012 OUT1_8 IF SHOW_RASTER=TRUE DEC $D020 ELSE LDA IA LDX IX LDY IY RTI ; ; Sprite routine address tables ; SPRITE_TABLE_L DFL SPRITE_1 DFL SPRITE_2 ; Addresses of each sprite routine DFL SPRITE_3 DFL SPRITE_4 DFL SPRITE_5 DFL SPRITE_6 DFL SPRITE_7 DFL SPRITE_8 SPRITE_TABLE_H DFH SPRITE_1 DFH SPRITE_2 DFH SPRITE_3 DFH SPRITE_4 DFH SPRITE_5 DFH SPRITE_6 DFH SPRITE_7 DFH SPRITE_8 ; ; DELAY - Used to sync the MAIN_LOOP to the raster ; DELAY LDA DELAYFLAG ; Wait for a change in DELAYFLAG BEQ DELAY DEC DELAYFLAG RTS ; ; GENLIST - Generates multiplexor sprite Y order ; GENLIST LDX #0 STX CNT INX SORT LDY PNT1-1,X LDA SY,Y LDY PNT1,X CMP SY,Y BCS ISOK LDA SY,Y STY TY STX TX DEX BACK DEX BMI FOUND LDY PNT1,X CMP SY,Y BEQ FOUND BCS BACK FOUND INX STX CNT LDX TX SHIFT_POINTER LDA PNT1-1,X STA PNT1,X DEX CPX CNT BNE SHIFT_POINTER LDA TY STA PNT1,X LDX TX ISOK INX CPX #NSP BNE SORT LDY #NSP-1 ; Find first sprite with a non-zero FINDFIRST LDX PNT1,Y LDA SY,X ; sprite Y value BNE FOUNDFIRST DEY BPL FINDFIRST LDY #0 FOUNDFIRST STY NXTSP LDX #NSP-1 ; Copy the buffered sprite coordinates COPYBUFFER LDA SX,X STA SX_BUFFER,X ; into the used coordinate buffer LDA SY,X STA SY_BUFFER,X DEX BPL COPYBUFFER RTS CLRVIC LDX #15 ; Clear the VIC chip LDA #0 CLRIT STA $D000,X DEX BPL CLRIT RTS ; ; BADDIES - Processes all baddy attack patterns ; BADDIES LDY #0 LDA (DATABASE),Y ; See if map counter is the same as CMP MAPCOUNT BNE NONEW ; the map value in the database INY LDA (DATABASE),Y CMP MAPCOUNT+1 BNE NONEW JSR SETBADS ; If not process any active baddies NONEW LDX #ALIENS-1 FINDON LDA ALIENON,X ; Find a free baddy BNE BADDYON DEX BPL FINDON RTS BADDYON LDA INTROCOUNT,X ; Countdown the introduction value BEQ COUNTEDIN DEC INTROCOUNT,X DEX BPL FINDON RTS COUNTEDIN LDA ALIENON,X ; See if alien needs initialising BMI SETON MOVEBADDY LDA EXPLODE_FLAGS,X ; Is the alien exploding ? BNE NEXT_BADDY LDA SY+4,X ; Add the new velocities to the ADD YVEL,X STA SY+4,X ; sprite coordinates CMP #$25 BCC ALLDONE CMP #250 BCS ALLDONE LDA SX+4,X ADD XVEL,X STA SX+4,X CMP #5 BCC ALLDONE CMP #165 BCS ALLDONE DEC BADDYCOUNT,X ; Decrement the velocity counter BEQ NEWVELS NEXT_BADDY DEX BPL FINDON RTS SETON LDA #1 ; Alien on, introduction off STA ALIENON,X LDA #$26 ; Initial alien Y value STA SY+4,X LDA BADDYX,X ; Baddy x value STA SX+4,X LDA BADDYCOLOUR,X ; Baddy colour STA SPRC+4,X LDA ANIML,X ; Baddy animation table address STA FROM LDA ANIMH,X STA FROM+1 LDY #0 LDA (FROM),Y STA SPRCHR+4,X ; Baddy pointer TYA STA ANIMATION_HALT,X ; Acctivate the animation sequencer NEWVELS LDA PATHSL,X ; Get baddy attack path address STA FROM LDA PATHSH,X STA FROM+1 LDY #0 ; Get the next velocities LDA (FROM),Y BEQ ALLDONE ; 0 = Terminator CMP #CHANGE_FRAME ; Check for animation instruction BEQ NEW_FRAMES GET_COUNTER STA BADDYCOUNT,X INY LDA (FROM),Y STA XVEL,X INY LDA (FROM),Y STA YVEL,X LDA PATHSL,X ; Add 3 to pattern address ADD #3 STA PATHSL,X BCC SKP INC PATHSH,X SKP DEX BMI DONE1 JMP FINDON DONE1 RTS ALLDONE LDA #0 ; Switch alien off STA ALIENON,X STA SY+4,X STA SX+4,X DEX BMI DONE2 JMP FINDON DONE2 RTS ; NEW_FRAMES INY ; Y=1 LDA (FROM),Y STA SPRCHR+4,X TYA STA ANIMATION_HALT,X ; Halt animation program on this alien LDA PATHSL,X ADD #2 STA PATHSL,X BCC SKP_CA INC PATHSH,X SKP_CA INY LDA (FROM),Y JMP GET_COUNTER ; SETBADS LDY #2 ; Get formation address LDA (DATABASE),Y STA FROM INY LDA (DATABASE),Y STA FROM+1 LDA DATABASE ; Add 4 to formation database ADD #4 STA DATABASE BCC SKP2 INC DATABASE+1 SKP2 LDY #0 LDA (FROM),Y STA ALNUM ; No of aliens in this formation TAX GETBADDY INY LDA (FROM),Y STA INTROTEMP,X ; Introduction counter INY LDA (FROM),Y STA BADDYXTEMP,X ; X corrdinate INY LDA (FROM),Y STA BADDYCUL,X ; Colour INY LDA (FROM),Y STA ADDRTEMPL,X ; Pattern address INY LDA (FROM),Y STA ADDRTEMPH,X ; " " DEX BNE GETBADDY LDY ALNUM FINDALIEN LDX #ALIENS-1 SEARCH LDA ALIENON,X ; Find a free alien to use BEQ FOUNDFREE DEX BPL SEARCH RTS FOUNDFREE LDA #$80 ; Alien on & introduce STA ALIENON,X LDA BADDYXTEMP,Y ; Pass on attack attributes STA BADDYX,X LDA BADDYCUL,Y BPL NO_POWER_UP ; Check if power up should be left PHA LDA #1 ; Signal a power up should be left STA LEAVE_FLAGS,X PLA AND #$7F NO_POWER_UP STA BADDYCOLOUR,X LDA INTROTEMP,Y STA INTROCOUNT,X LDA ADDRTEMPL,Y STA FROM LDA ADDRTEMPH,Y STA FROM+1 STY TEMPY LDY #0 LDA (FROM),Y STA BULTYPE,X ; Alien bullet type INY LDA (FROM),Y STA BULCOUNT,X ; Bullet fire rate LDA #0 STA BULCOUNT2,X INY LDA (FROM),Y STA ANIML,X ; Animation table address INY LDA (FROM),Y STA ANIMH,X ; " " " LDA #0 STA ANIMINDEX,X ; 0 the index with the table INY LDA (FROM),Y STA ANIMSPEED,X ; Speed of animation STA ANIMSPEED2,X INY LDA (FROM),Y STA DESTROYSHOTS,X ; No of shots to kill a baddy LDA FROM ADD #6 STA PATHSL,X ; Add 9 to the table address LDA FROM+1 ADC #0 STA PATHSH,X NOHIGHBYTE LDY TEMPY ; Do the next alien in the formation DEY BEQ PATHSSET JMP FINDALIEN PATHSSET RTS ; ; ANIMATEBADS - Processes the animation of the baddies ; ANIMATEBADS LDX #ALIENS-1 TRYTHIS LDA ALIENON,X ; Alien active ? BNE DOTHIS DEX BPL TRYTHIS RTS DOTHIS LDA EXPLODE_FLAGS,X ; Is the alien exploding ? BEQ CAN_DO DEX BPL TRYTHIS RTS CAN_DO LDA ANIMATION_HALT,X BEQ CAN_DO_2 DEX BPL TRYTHIS RTS CAN_DO_2 LDA ANIMSPEED,X ; Need a new frame yet ? BEQ DONEXTFRAME DEC ANIMSPEED,X DEX BPL TRYTHIS RTS DONEXTFRAME LDA ANIMSPEED2,X STA ANIMSPEED,X LDA ANIML,X ; Get the animation table address STA FROM LDA ANIMH,X STA FROM+1 DOFRAME LDY ANIMINDEX,X ; Get the index within the table LDA (FROM),Y BEQ RESETINDEX STA SPRCHR+4,X ; Update the pointer INC ANIMINDEX,X DEX ; Next baddy BPL TRYTHIS RTS RESETINDEX LDA #0 ; Reset the index within the table STA ANIMINDEX,X JMP DOFRAME ; ; LINEDRAW - Initialises a bullet to linedraw towards the players' ship ; LINEDRAW LDY #BULLETS-1 FINDBUL LDA BULON,Y ; Find a free bullet BEQ FOUNDBUL DEY BPL FINDBUL RTS FOUNDBUL LDA SY+4,X ; Get alien Y pos STA SY+14,Y ; and bullet sprite Y pos LDA SX+4,X ; Get alien X pos STA SX+14,Y ; and bullet sprite X pos JSR GRADIENT ; Calculate the lines' gradient LDA #$D6 ; Bullet sprite pointer STA SPRCHR+14,Y LDA #2 ; Bullet sprite colour STA SPRC+14,Y LDA #1 ; Flag the bullet on STA BULON,Y RTS GRADIENT LDA SX+14,Y ; MyX < BulletX then -ve X direction SUB SX BCS PLUSX LDA SX ; MyX - BulletX = DIF +ve direction SUB SX+14,Y STA XDIF LDA #2 STA DIRX,Y JMP GETY PLUSX STA XDIF ; BulletX - MyX = DIF -ve X direction LDA #-2 STA DIRX,Y GETY LDA SY+14,Y ; As in X SUB SY BCS PLUSY LDA SY SUB SY+14,Y STA YDIF LDA #2 STA DIRY,Y JMP GOTVALS PLUSY STA YDIF LDA #-2 STA DIRY,Y GOTVALS LDA YDIF ; YDIF > XDIF CMP XDIF BCS INTY INTX LDA #-1 STA BULLINTX,Y LDA XDIF STA BULVAR,Y STA BULST,Y LDA YDIF STA BULLINTY,Y RTS INTY LDA #-1 STA BULLINTY,Y LDA YDIF STA BULVAR,Y STA BULST,Y LDA XDIF STA BULLINTX,Y RTS ; ; OCTO_FIRE - The initialisation routine for the 8 way firing baddies ; OCTO_FIRE LDY #7 COUNT_BULLETS LDA BULON,Y ; Are there 8 bullets available BNE NOT_ENUF DEY BPL COUNT_BULLETS LDY #7 SET_DIRECTION LDA #$FF ; Initial X/Y integers STA BULLINTX,Y STA BULLINTY,Y LDA BLASTTAB_X,Y ; X/Y directions STA DIRX,Y LDA BLASTTAB_Y,Y STA DIRY,Y LDA SX+4,X ; X offsets from base alien ADD BLASTOFF_X,Y STA SX+14,Y LDA SY+4,X ; Y offsets from base alien ADD BLASTOFF_Y,Y STA SY+14,Y LDA #1 STA SPRC+14,Y LDA #$50 STA SPRCHR+14,Y STA BULON,Y ; Trigger this bullet DEY BPL SET_DIRECTION NOT_ENUF RTS ; BLASTTAB_X DFL 0,2,2,2,0,-2,-2,-2 BLASTTAB_Y DFL -4,-4,0,4,4,4,0,-4 BLASTOFF_X DFL 0,12,12,12,0,-12,-12,-12 BLASTOFF_Y DFL -21,-21,0,21,21,21,0,-21 ; ; ; BADDYBULS - Processes all types of baddy bullets ; BADDYBULS LDX #ALIENS-1 SEARCH1 LDA ALIENON,X BNE TESTBUL DEX BPL SEARCH1 JMP FIREBULLETS TESTBUL LDA EXPLODE_FLAGS,X ; No bullets to be fired BEQ TESTBUL_2 DEX ; if the alien is exploding BPL SEARCH1 JMP FIREBULLETS TESTBUL_2 LDA BULTYPE,X BNE CANFIRE DEX BPL SEARCH1 JMP FIREBULLETS CANFIRE LDA BULCOUNT2,X BEQ SETONBULLET DEC BULCOUNT2,X DEX BPL SEARCH1 JMP FIREBULLETS SETONBULLET LDA BULCOUNT,X ; Reset fire rate STA BULCOUNT2,X LDA BULTYPE,X ASL TAY LDA BULTYPES+0,Y STA JUMPER+1 LDA BULTYPES+1,Y STA JUMPER+2 JUMPER JSR $AAAA ; Self Modified DEX BPL SEARCH1 FIREBULLETS LDX #BULLETS-1 SCAN1 LDA BULON,X BNE DOBUL DEX BPL SCAN1 JMP PULSEBULS DOBUL LDA BULLINTY,X CMP #$FF BNE MOVEX LDA DIRY,X ADD SY+14,X STA SY+14,X CMP #30 BCC BULOFF CMP #250 BCS BULOFF LDA BULVAR,X SUB BULLINTX,X STA BULVAR,X BCS NOMOVEX ADC BULST,X STA BULVAR,X LDA DIRX,X ADD SX+14,X STA SX+14,X CMP #5 BCC BULOFF CMP #165 BCS BULOFF NOMOVEX DEX BPL SCAN1 JMP PULSEBULS MOVEX LDA BULVAR,X SUB BULLINTY,X STA BULVAR,X BCS NOMOVEY ADC BULST,X STA BULVAR,X LDA DIRY,X ADD SY+14,X CMP #30 BCC BULOFF CMP #250 BCS BULOFF STA SY+14,X NOMOVEY LDA DIRX,X ADD SX+14,X CMP #5 BCC BULOFF CMP #165 BCS BULOFF STA SX+14,X DEX BMI BULDONE JMP SCAN1 BULDONE JMP PULSEBULS BULOFF LDA #0 STA BULON,X STA SX+14,X STA SY+14,X DEX BMI BULDONE JMP SCAN1 ; ; PULSEBULS - ; PULSEBULS LDA PULSETIME ADD #1 AND #7 STA PULSETIME BEQ DOPULSE RTS DOPULSE LDA PULSEIND ADD #1 AND #7 STA PULSEIND TAX LDY PULSECULS,X LDX #BULLETS-1 SCANBULS LDA BULON,X BNE BULISON DEX BPL SCANBULS RTS BULISON TYA STA SPRC+14,X DEX BPL SCANBULS RTS PULSECULS DFB 2,10,1,0,0,1,10,2 BULTYPES DFW $0000 ; Bullet type routine table DFW LINEDRAW DFW OCTO_FIRE ; ; LOCK - Background locks any sprite with it's LOCKON flag set ; LOCK LDX #LOCKED_STUFF-1 TRYLOCK LDA LOCKON,X BNE ISLOCKED DEX BPL TRYLOCK RTS ISLOCKED LDA SY,X ADD #1 STA SY,X CMP #250-8 BCS LOCKOFF DEX BPL TRYLOCK RTS LOCKOFF LDA #0 STA LOCKON,X STA SX,X STA SY,X DEX BPL TRYLOCK RTS ;------------------------------------------------------------------------------ ; Formation sequencer BADDYDATA ; DFW 0030 ; DFW BLASTER DFW 0045 DFW WALL DFW 0070 DFW BLASTER ; 8 way bullet firing alien DFW 0080 DFW GRIB_FORM1 ; Gribblies left DFW 0085 DFW BLASTER DFW 0090 DFW GRIB_FORM2 ; Gribblies right DFW 0095 DFW BLASTER DFW 0110 DFW WALL ; 3 gribblies either side firing DFW 0130 DFW BLASTER ;------------------------------------------------------------------------------ ; Baddy formations GRIB_FORM1 DFB 4 ; No of aliens DFB 0 ; Intro time DFB 40 ; X coord DFB BLUE ; Colour+power up DFW DOWN1 ; Pattern addr DFB 21 DFB 28 DFB BLUE DFW DOWN2 DFB 21 DFB 52 DFB BLUE DFW DOWN3 DFB 42 DFB 40 DFB BLUE DFW DOWN4 ;------------ GRIB_FORM2 DFB 4 ; No of aliens DFB 0 ; Intro time DFB 40+80 ; X coord DFB BLUE ; Colour+power up DFW DOWN1 ; Pattern addr DFB 21 DFB 28+80 DFB BLUE DFW DOWN2 DFB 21 DFB 52+80 DFB BLUE DFW DOWN3 DFB 42 DFB 40+80 DFB BLUE DFW DOWN4 ;------------ BLASTER DFB 4 ; No of aliens DFB 0 ; Intro time DFB 25 ; X coord DFB RED+POWER_UP ; Colour+power up DFW BLAST_PATTERN ; Pattern addr DFB 21 ; Intro time DFB 25 ; X coord DFB RED ; Colour+power up DFW BLAST_PATTERN ; Pattern addr DFB 42 ; Intro time DFB 25 ; X coord DFB RED ; Colour+power up DFW BLAST_PATTERN ; Pattern addr DFB 63 ; Intro time DFB 25 ; X coord DFB RED ; Colour+power up DFW BLAST_PATTERN ; Pattern addr ;------------- WALL DFB 6 ; No of aliens DFB 0 ; Intro time DFB 40 ; X coord DFB BLUE ; Colour+power up DFW WALL_LEFT_F ; Pattern addr DFB 35 ; Intro time DFB 40 ; X coord DFB BLUE ; Colour DFW WALL_LEFT ; Pattern addr DFB 70 ; Intro time DFB 40 ; X coord DFB BLUE ; Colour DFW WALL_LEFT ; Pattern addr DFB 0 ; Intro time DFB 120 ; X coord DFB BLUE ; Colour DFW WALL_RIGHT_F ; Pattern addr DFB 35 ; Intro time DFB 120 ; X coord DFB BLUE ; Colour DFW WALL_RIGHT ; Pattern addr DFB 70 ; Intro time DFB 120 ; X coord DFB BLUE ; Colour DFW WALL_RIGHT ; Pattern addr ;------------------------------------------------------------------------------ ; Baddy patterns DOWN1 DFB NOFIRE ; Bullet type DFB 20 ; Bullet rate DFW GRIB_UP ; Animation addr DFB 4 ; Animation speed DFB 3 ; Number of hits DFB 200 ; Counter DFB 0 ; X velocity DFB 1 ; Y velocity DFB FIN ; Terminate pattern ;----------- DOWN2 DFB NOFIRE ; Bullet type DFB 0 ; Bullet rate DFW GRIB_RIGHT ; Animation addr DFB 4 ; Animation speed DFB 3 ; Number of hits DFB 200 ; Counter DFB 0 ; X velocity DFB 1 ; Y velocity DFB FIN ; Terminate pattern ;----------- DOWN3 DFB NOFIRE ; Bullet type DFB 0 ; Bullet rate DFW GRIB_LEFT ; Animation addr DFB 4 ; Animation speed DFB 3 ; Number of hits DFB 200 ; Counter DFB 0 ; X velocity DFB 1 ; Y velocity DFB FIN ; Terminate pattern ;----------- DOWN4 DFB NOFIRE ; Bullet type DFB 0 ; Bullet rate DFW GRIB_DOWN ; Animation addr DFB 4 ; Animation speed DFB 3 ; Number of hits DFB 200 ; Counter DFB 0 ; X velocity DFB 1 ; Y velocity DFB FIN ; Terminate pattern ;----------- BLAST_PATTERN DFB OCTO ; Bullet type DFB 0 ; Bullet rate DFW BLAST_ANIM ; Animation addr DFB 4 ; Animation speed DFB 10 ; Number of hits DFB CHANGE_FRAME,$73 DFB 40 ; Counter DFB +1 ; X velocity DFB 2 ; Y velocity DFB CHANGE_FRAME,$72 DFB 20 DFB +1 DFB 0 DFB CHANGE_FRAME,$73 DFB 20 DFB 1 DFB 2 DFB CHANGE_FRAME,$6C DFB 40 DFB 1 DFB 0 DFB CHANGE_FRAME,$6D DFB 20 DFL -1 DFB 2 DFB CHANGE_FRAME,$6E DFB 20 DFL -1 DFB 0 DFB CHANGE_FRAME,$6F DFB 20 DFL -1 DFL -2 DFB CHANGE_FRAME,$70 DFB 200 DFB 0 DFL -2 DFB FIN ; Terminate pattern ;----------- WALL_LEFT DFB NOFIRE ; Bullet type DFB 0 ; Bullet rate DFW GRIB_DOWN ; Animation addr DFB 4 ; Animation speed DFB 5 ; Number of hits DFB 50 ; Counter DFB 0 ; X velocity DFB 1 ; Y velocity DFB 40 DFB 2 DFB 1 DFB 200 DFB 0 DFB 1 DFB FIN ; Terminate pattern ;----------- WALL_RIGHT DFB NOFIRE ; Bullet type DFB 0 ; Bullet rate DFW GRIB_DOWN ; Animation addr DFB 4 ; Animation speed DFB 5 ; Number of hits DFB CHANGE_FRAME,$6C DFB 50 ; Counter DFB 0 ; X velocity DFB 1 ; Y velocity DFB CHANGE_FRAME,$6D DFB 40 DFL -2 DFB 1 DFB CHANGE_FRAME,$6C DFB 200 DFB 0 DFB 1 DFB FIN ; Terminate pattern ;----------- WALL_LEFT_F DFB LINE ; Bullet type DFB 90 ; Bullet rate DFW GRIB_DOWN ; Animation addr DFB 4 ; Animation speed DFB 5 ; Number of hits DFB 200 ; Counter DFB 0 ; X velocity DFB 1 ; Y velocity DFB FIN ; Terminate pattern ;----------- WALL_RIGHT_F DFB LINE ; Bullet type DFB 90 ; Bullet rate DFW GRIB_DOWN ; Animation addr DFB 4 ; Animation speed DFB 5 ; Number of hits DFB 200 ; Counter DFB 0 ; X velocity DFB 1 ; Y velocity DFB FIN ; Terminate pattern ;------------------------------------------------------------------------------ ; Baddy animation tables GRIB_UP DFB $87,$88,$89,$89,$88,$87,0 GRIB_DOWN DFB $7A,$7B,$7C,$7C,$7B,$7A,0 GRIB_LEFT DFB $8D,$8E,$8F,$8F,$8E,$8D,0 GRIB_RIGHT DFB $8A,$8B,$8C,$8C,$8B,$8A,0 BLAST_ANIM DFB $74,$75,$76,$77,$78,$79,$7A,$7B,$7C,0 ;------------------------------------------------------------------------------ ; XD DFB 0 ; Linedraw variables XE DFB 0 YD DFB 0 YE DFB 0 A00 DFB 0 A1O DFB 0 S0 DFB 0 S1 DFB 0 D11 DFB 0 LG DFB 0 SH DFB 0 TS DFB 0 TTO DFB 0 CT2 DFB 0 UD DFB 0 XP DFW 0 YP DFW 0 TEMP3 DFB 0 ; ; TITLE_SEQUENCE - Handles the game title sequence (obvious really!) ; ENT TITLE_SEQUENCE SEI LDX #$FF TXS INX STX $D020 STX $D021 STX $D01C ; Multi colour sprites off STX $D010 ; Clear sprite X MSB STX $D015 INX STX CIRCLE_FLAG ; Stop big circle LDA #$C8 ; Multi colour chars off STA $D016 LDA #$1B ; Screen on & reset screen Y pos STA $D011 CLS_A LDA #$40 STA $C800,X ; Clear out screen A STA $C900,X STA $CA00,X STA $CB00,X LDA #12 STA $D800,X STA $D900,X STA $DA00,X STA $DB00,X INX BNE CLS_A LDA #$35 STA 1 LDA #T1 ; Title interrupts STA $FFFE LDA ^T1 STA $FFFF LDA #$7F ; Enable raster interrupts AND $D011 STA $D011 STA $DC0D ; Clear any spurious interrupts STA $DD0D LDA #$FB ; Raster at the bottom STA $D012 INX STX $D019 ; Acknowledge interrupts STX $D01A LDA #$C0 ; Bank 3 STA $DD00 LDA #$21 ; Screen @$C800, Chars @$C000 STA $D018 INX ; X=2 LDA #0 CLR_ZP STA $00,X INX BNE CLR_ZP LDA #8 STA SHIFT_COUNT ; Set window scroll to 8 LDA #WINDOW_TEXT ; Scrolling window data STA WINDOW_MES LDA ^WINDOW_TEXT STA WINDOW_MES+1 JSR CLEAR_WORKSET ; Clear out the char-set LDA #$05 ; Point fade routines to charset STA CHAR_BASE+1 STA CHAR_BASE_2+1 CLI ; Interrupts enabled LDX #1 ; High score tune JSR TUNE JSR GEN_STARFIELD ; Generate the starfield JSR HIGHSCORES ; See if player has a high score. LDX #4 INIT_LOGO LDA #$65 ; Initialise game logo STA $CBF8,X LDA #BLUE STA $D027,X DEX BPL INIT_LOGO LDA #MGREY STA $D025 ; Sprite multi-colour 1 LDA #LGREY STA $D026 ; Sprite multi-colour 2 LDA #172 ; Put the player's ship on screen STA $D00A ; Sprite 5 X LDA #117 STA $D00B ; Sprite 5 Y LDA #134 STA $D00D ; Sprite 6 Y STA $D00F ; Sprite 7 Y LDA #172-12 STA $D00C ; Sprite 6 X LDA #172+12 ; Sprite 7 X STA $D00E LDX #$40 ; Ship sprite pointers STX $CBFD ; 5 INX STX $CBFE ; 6 INX STX $CBFF ; 7 LDA #7 ; Ship sprite colours STA $D02C LDA #2 STA $D02D STA $D02E LDX #2 ; Set title tune JSR TUNE LDX #0 ; Sprites off STX $D015 STX $D01B STX CIRCLE_FLAG ; Circle on TITLE_LOOP JSR DERES LDX #$FF ; Sprites on STX $D015 STX $D01C ; Sprite multi-colour enabled JSR INIT_MATRIX LDX #TITLE_PAGE LDY ^TITLE_PAGE JSR SPRINT JSR FADE_IN LDX #250 JSR HALT JSR DERES JSR INIT_MATRIX LDA #0 STA $D015 LDX #CREDIT_PAGE LDY ^CREDIT_PAGE JSR SPRINT JSR FADE_IN LDX #250 JSR HALT JSR DERES JSR INIT_MATRIX LDX #HIGH_TABLE LDY ^HIGH_TABLE JSR SPRINT JSR FADE_IN JSR PRINT_HIGHS LDX #250 JSR HALT JMP TITLE_LOOP ; ; GAME_INIT - Called after a fire signal from TITLE_LOOP, prepares for game ; GAME_INIT LDX #0 STX $D015 STX $D418 STX $D01B STX MFL_A STX MFL_B STX MFL_C LDX #$16 ; Clear the SID chip STOP_SID LDA #8 STA SID,X LDA #0 STA SID,X DEX BPL STOP_SID JSR TRENDY_CLEAR JSR CLS ; Clear the screen & exit (!) JMP GAME_START ; ; T1 - The main raster controlling titles and high scores ; T1 STA IA STX IX STY IY CLD DEC $D019 IF SHOW_RASTER=TRUE LDA #2 STA $D020 ELSE INC LASTCOUNT JSR STAR_FIELD IF SHOW_RASTER=TRUE LDA #7 STA $D020 ELSE JSR WINDOW_SCROLL IF SHOW_RASTER=TRUE LDA #5 STA $D020 ELSE LDA CIRCLE_FLAG BNE NO_CIRCLE JSR BIG_CIRCLE NO_CIRCLE IF SHOW_RASTER=TRUE LDA #6 STA $D020 ELSE JSR REFRESH IF SHOW_RASTER=TRUE LDA #0 STA $D020 ELSE LDA IA LDX IX LDY IY RTI ; ; PRINT_HIGHS - Prints the High Score Table during the title sequence ; PRINT_HIGHS LDA #$C800+04*40+8 STA TO STA TO2 LDA ^$C800+04*40+8 STA TO+1 ADD #$D8-$C8 STA TO2+1 LDA #SCoRES STA FROMM LDA ^SCoRES STA FROMM+1 LDX #9 PRINT_LINE LDY #$27 LDA #0 FILL_COLOUR STA (TO2),Y DEY BPL FILL_COLOUR LDY #0 PRINT_NAMES LDA (FROMM),Y AND #$3F ASL STA (TO),Y INC TO BNE NO_1 INC TO+1 NO_1 ADD #1 STA (TO),Y INC TO BNE NO_2 INC TO+1 NO_2 INY CPY #3 BNE PRINT_NAMES LDA TO ADD #3 STA TO BCC PRINT_SCORES INC TO+1 PRINT_SCORES LDA (FROMM),Y LSR LSR LSR LSR ORA #$30 ASL STA (TO),Y INC TO BNE NO_4 INC TO+1 NO_4 ADD #1 STA (TO),Y INC TO BNE NO_5 INC TO+1 NO_5 LDA (FROMM),Y AND #$0F ORA #$30 ASL STA (TO),Y INC TO BNE NO_6 INC TO+1 NO_6 ADD #1 STA (TO),Y INY CPY #6 BNE PRINT_SCORES STX X_TEMP LDY #4 FADE_COLOUR LDA COLOUR_FADE,Y STY Y_TEMP LDY #$27 FILL_LINE STA (TO2),Y DEY BPL FILL_LINE LDX #3 JSR WAIT LDY Y_TEMP DEY BPL FADE_COLOUR LDX X_TEMP LDA FROMM ADD #6 STA FROMM BCC NO_7 INC FROMM+1 NO_7 LDA TO ADD #22+40 STA TO BCC NO_8 INC TO+1 NO_8 LDA TO2 ADD #80 STA TO2 BCC NO_9 INC TO2+1 NO_9 DEX BMI DONE_ALL JMP PRINT_LINE DONE_ALL RTS ; X_TEMP DFB 0 Y_TEMP DFB 0 COLOUR_FADE DFB 1,15,12,11,0 ; ; BIG_CIRCLE - Spins 8 sprites in a pseudo circle ; BIG_CIRCLE LDX #0 LDY CIRCLE_INDEX SPIN_LOOP LDA CIRCLE_X,Y STA $D000,X LDA CIRCLE_Y,Y ADD #12 STA $D001,X TYA ADD #50 TAY INX INX CPX #10 BNE SPIN_LOOP INC CIRCLE_INDEX INC CIRCLE_INDEX RTS ; CIRCLE_INDEX DFB 0 CIRCLE_FLAG DFB 0 ; ; ; WINDOW_SCROLL - Scrolls player details in an 8 byte wide window ; WINDOW_SCROLL LDX #7 SHIFT_WINDOW ASL $C000+$E4*8,X ; Shift window one pixel to the left ROL $C000+$E3*8,X ROL $C000+$E2*8,X ROL $C000+$E1*8,X ROL $C000+$E0*8,X ROL $C000+$DF*8,X ROL $C000+$DE*8,X ROL $C000+$DD*8,X ROL $C000+$DC*8,X DEX BPL SHIFT_WINDOW LDA SHIFT_COUNT BEQ GET_NEW_CHAR DEC SHIFT_COUNT RTS GET_NEW_CHAR LDA #8 STA SHIFT_COUNT LDY #0 STY CALC+1 GRAB_LETTER LDA (WINDOW_MES),Y BEQ RESET_MES AND #$3F ASL ROL CALC+1 ASL ROL CALC+1 ASL ROL CALC+1 ADD #$0500+$80*8 STA CALC LDA CALC+1 ADC ^$0500+$80*8 STA CALC+1 LDY #7 DUMP_WINDOW LDA (CALC),Y STA $C000+$E4*8,Y DEY BPL DUMP_WINDOW INC WINDOW_MES BNE PS_1 INC WINDOW_MES+1 PS_1 RTS RESET_MES LDA #WINDOW_TEXT STA WINDOW_MES LDA ^WINDOW_TEXT STA WINDOW_MES+1 JMP GRAB_LETTER ; SHIFT_COUNT DFB 0 ; ; ; HIGHSCORES - sorts the highscore table ; HIGHSCORES LDA PLRSC ORA PLRSC+1 ORA PLRSC+2 BNE IS_SC JMP BUFFER_SCORES IS_SC LDA #SCoRES STA SCX LDA ^SCoRES STA SCX+1 LDA #13 STA SCORE_LINE LDX #10 CHECKNEX LDY #5 ; Subtract table score from player LDA PLRSC+2 SUB (SCX),Y ; score DEY LDA PLRSC+1 SBC (SCX),Y DEY LDA PLRSC SBC (SCX),Y BCS IN_HI NEXT_SCORE INC SCORE_LINE LDA SCX ; get next highest score entry ADD #6 STA SCX BCC NOCAR INC SCX+1 NOCAR DEX BNE CHECKNEX RTS ; Didn't make the table IN_HI LDA #SCoREBOT STA TO LDA ^SCoREBOT STA TO+1 LDA #SCoREBOT-6 STA FROMM LDA ^SCoREBOT-6 STA FROMM+1 SHIFT LDY #5 MOVEDOWN LDA (FROMM),Y ; Shift the table below players score STA (TO),Y DEY BPL MOVEDOWN LDA FROMM ; Reached the correct position CMP SCX BNE NEXTSHIFT LDA FROMM+1 CMP SCX+1 BNE NEXTSHIFT JMP SHIFTDONE ; All done. NEXTSHIFT LDA FROMM ; Shift down the next score SUB #6 STA FROMM BCS SKIPX DEC FROMM+1 SKIPX LDA TO SUB #6 STA TO BCS SKIP2X DEC TO+1 SKIP2X JMP SHIFT SHIFTDONE LDA #$20 ; Blank that name entry LDY #2 CLRNAM STA (SCX),Y DEY BPL CLRNAM LDY #5 LDX #2 ; Copy in the new players score COPSCoRE LDA PLRSC,X STA (SCX),Y DEY DEX BPL COPSCoRE JSR CLEAR_WORKSET ; Clear out workspace charset JSR BUFFER_SCORES JSR GEN_STARFIELD LDX #CONGRAT_MES ; Print congratulation message LDY ^CONGRAT_MES JSR SPRINT LDA SCORE_LINE ; Calculation to highlite player ASL TAX ; score LDA YTABLE+0,X STA SCREEN_ADDR+1 STA COLOUR_ADDR+1 LDA YTABLE+1,X STA SCREEN_ADDR+2 ADD #$D8-$C8 STA COLOUR_ADDR+2 LDX #10 LDA #1 COLOUR_ADDR STA $FFFF,X ; Self Modified DEX BPL COLOUR_ADDR LDA #SCoRES ; High score table base address STA FROMM LDA ^SCoRES STA FROMM+1 LDA #$C800+13*40 ; High score table base print STA TO LDA ^$C800+13*40 ; address STA TO+1 LDX #9 ; No of scores-1 PRINT_TABLE LDY #2 ; No of BCD digits-1 PRINT_NAME LDA (FROMM),Y AND #$3F ORA #$80 ; Small character set STA (TO),Y DEY BPL PRINT_NAME INC TO BNE SKIP_1 INC TO+1 SKIP_1 LDY #3 PRINT_DIGITS LDA (FROMM),Y LSR ; Left nybble LSR LSR LSR ORA #$B0 ; Small character set + $30 STA (TO),Y INC TO BNE SKIP_2 INC TO+1 SKIP_2 LDA (FROMM),Y ; Right nybble AND #$0F ORA #$B0 STA (TO),Y SKIP_3 INY ; Next digit CPY #6 BNE PRINT_DIGITS LDA FROMM ; Next score position ADD #6 STA FROMM BCC SKIP_4 INC FROMM+1 SKIP_4 LDA TO ; Next sceen line ADD #36 STA TO BCC SKIP_5 INC TO+1 SKIP_5 DEX ; next score BPL PRINT_TABLE JMP MUTATE_IT ; Goto the mutator ; ; BUFFER_SCORES - Buffers Player 1 & high score into scrolling window ; BUFFER_SCORES LDX #0 LDY #0 BUFFER_DUMP LDA SCoRES+3,X LSR LSR LSR LSR ORA #$30 STA BUFFER_2,Y LDA SCoRES+3,X AND #$0F ORA #$30 STA BUFFER_2+1,Y LDA PLRSC,X LSR LSR LSR LSR ORA #$30 STA BUFFER_1,Y LDA PLRSC,X AND #$0F ORA #$30 STA BUFFER_1+1,Y LDA SCoRES,X STA NAME_BUFFER,X INY INY INX CPX #3 BNE BUFFER_DUMP RTS ; ; CLEAR_WORKSET - Clears out the workspace charset ; CLEAR_WORKSET LDX #0 TXA CLR_CHARS STA $C000,X ; Clear out workspace charset STA $C100,X STA $C200,X STA $C300,X STA $C400,X STA $C500,X STA $C600,X STA $C700,X INX BNE CLR_CHARS RTS ; ; Title text entries ; CONGRAT_MES DFB DW,14,13,14:DFM "WHAT A HERO" DFB AT,13,15,07:DFM "YOU AMASSED A MEGA SCORE" DFB AT,11,17,05:DFM "ENTER YOUR NAME IN THE RANKS" DFB FIN TITLE_PAGE DFB AT,08,24,14:DFM "COPYIGHT RAINBIRD , 1988" DFB DW,10,22,05:DFM "PRESS FIRE" DFB FIN CREDIT_PAGE DFB DW,11,05,07:DFM "THE GRAFT" DFB AT,14,07,06:DFM "PAUL HUGHES" DFB DW,10,10,07:DFM "THE PIXELS" DFB AT,15,12,06:DFM "DAWN DRAKE" DFB DW,11,15,07:DFM "THE SOUND" DFB AT,13,17,06:DFM "HENRY MANCINI" DFB DW,10,20,07:DFM "THE DELAYS" DFB AT,11,22,06:DFM "SIMON WHATSISFACE" DFB DW,05,02,01:DFM "* THE CREDITS *" DFB FIN HIGH_TABLE DFB DW,02,02,05:DFM "* ROLL OF HONOUR *" DFB FIN WINDOW_TEXT DFM "AXION COPYRIGHT 1988 RAINBIRD........" DFM "LAST SCORE " BUFFER_1 DFM "000000" DFM "........TODAYS HIGHEST " BUFFER_2 DFM "068000 - " NAME_BUFFER DFM "P-H " DFM "........" DFB FIN ; ; The Top 10 High Scores ; SCoRES DFM "P-H":DFB $06,$80,$00 DFM "DYD":DFB $00,$70,$00 DFM "J-D":DFB $00,$60,$00 DFM "SWR":DFB $00,$50,$00 DFM "JCB":DFB $00,$40,$00 DFM "SPB":DFB $00,$30,$00 DFM "JIM":DFB $00,$20,$00 DFM "APD":DFB $00,$10,$00 DFM "CAZ":DFB $00,$09,$00 DFM "ICE":DFB $00,$00,$00 SCoREBOT DFM " ":DFB 0,0,0 ; ; Letter construction data 44 bytes each. Points follow contiguously ; POINTS EQU 22 ; How many points there are to draw LETTER_A DFB 00,20,00,18,00,16,00,14,00,07,07,00 DFB 22,00,22,02,22,04,22,06,22,08,22,20,17,20 DFB 17,13,08,13,08,09,17,09,17,04,10,04 DFB 05,09,05,20,00,20 LETTER_B DFB 00,20,05,20,05,04,14,04,17,07,17,08 DFB 08,08,08,12,15,12,17,14,17,16 DFB 08,16,08,20,22,20,22,13,20,11 DFB 20,10,22,08,22,05,17,00,00,00,00,20 LETTER_C DFB 00,20,02,20,04,20,06,20,08,20,10,20,12,20,22,20,22,16,05,16 DFB 05,09,10,04,12,04,14,04,16,04,18,04,20,04,22,04 DFB 22,00,07,00,00,07,00,20 LETTER_D DFB 00,20,02,20,04,20,06,20,08,20,10,20,12,20,15,20 DFB 19,20,22,17,22,07,15,00 DFB 00,00,00,14,05,14,05,04,12,04,17,09 DFB 17,14,15,16,00,16,00,20 LETTER_E DFB 00,20,00,18,00,16,00,14 DFB 00,12,00,10,00,07,07,00,22,00,22,04,10,04 DFB 06,08,17,08,17,12,05,12,05,16,22,16 DFB 22,20,20,20,18,20,16,20,00,20 LETTER_F DFB 00,20,05,20,05,18,05,16,05,14,05,12,17,12,17,08 DFB 06,08,10,04,12,04,14,04,16,04,22,04 DFB 22,00,07,00,00,07,00,09,00,11,00,13,00,15,00,20 LETTER_G DFB 00,20,00,07,07,00,22,00,22,04,10,04 DFB 05,09,05,16,17,16,17,13,15,13,15,09 DFB 22,09,22,20,20,20,18,20,16,20,14,20,12,20 DFB 06,20,04,20,00,20 LETTER_H DFB 00,20,05,20,05,12,17,12 DFB 17,20,22,20,22,00,17,00,17,08,05,08,05,00 DFB 00,00,00,02,00,04,00,06,00,08,00,10,00,12 DFB 00,14,00,16,00,18,00,20 LETTER_I DFB 03,20,03,16,08,16,08,04,03,04 DFB 03,00,18,00,18,04,13,04,13,06,13,08,13,10,13,16,18,16,18,20 DFB 16,20,14,20,12,20,10,20,08,20,06,20,03,20 LETTER_J DFB 03,20,05,20,07,20,09,20,13,16,13,14,13,12,13,10,13,04 DFB 18,04,18,00,03,00,03,04 DFB 08,04,08,06,08,08,08,10,08,12,08,14,06,16,03,16 DFB 03,20 LETTER_K DFB 00,20,05,20,05,12,06,12,14,20 DFB 20,20,19,19,11,11,11,09,19,01,19,00 DFB 14,00,06,08,05,08,05,00,00,00,00,02,00,04,00,06,00,08 DFB 00,10,00,20 LETTER_L DFB 00,20,00,18,00,16,00,14,00,12,00,10 DFB 00,07,07,00,10,00,10,04 DFB 05,09,05,16,22,16,22,20,20,20,18,20,16,20,14,20,12,20 DFB 10,20,08,20 DFB 00,20 LETTER_M DFB 00,20,05,20,05,06,06,06,10,10 DFB 12,10,16,06,17,06,17,20,22,20,22,18,22,16,22,14,22,12 DFB 22,10,22,00 DFB 17,00,12,05,10,05,05,00,00,00,00,20 LETTER_N DFB 00,20,00,18,00,16,00,14,00,12,00,10,00,08,00,06 DFB 00,04,00,02,00,00 DFB 05,00,17,12,17,00 DFB 22,00,22,20,17,20,17,17,05,05,05,20,03,20 DFB 00,20 LETTER_O DFB 00,20,02,20,04,20,06,20,08,20,10,20,12,20,14,20,16,20 DFB 18,20,22,20,22,00,07,00 DFB 00,07,00,14,05,14,05,09 DFB 10,04,17,04,17,16,00,16 DFB 00,20 LETTER_P DFB 00,20,00,18,00,16,00,14,00,12,00,10 DFB 00,08,17,08,17,04 DFB 03,04,07,00,22,00,22,02,22,04,22,06,22,08,22,10 DFB 22,12 DFB 05,12,05,20,03,20,00,20 LETTER_Q DFB 00,20,02,20,04,20,06,20,08,20,10,20,12,20 DFB 14,20,14,16,05,16 DFB 05,09,10,04,17,04,17,20 DFB 22,20,22,00,07,00,00,07 DFB 00,09,00,11,00,13,00,20 LETTER_R DFB 00,20,00,18,00,16,00,00,17,00,22,05 DFB 22,08,20,10,20,11,22,13 DFB 22,20,17,20,17,14,15,12 DFB 08,12,08,08,17,08,17,07 DFB 14,04,05,04,05,20,00,20 LETTER_S DFB 00,20,22,20,22,08,07,08 DFB 07,07,10,04,22,04,22,00 DFB 07,00,00,07,00,12,02,12,04,12,17,12 DFB 17,16,15,16,13,16,11,16,09,16,00,16,00,18,00,20 LETTER_T DFB 08,20,13,20,13,04,22,04 DFB 22,00,20,00,18,00,16,00,14,00,12,00,10,00,08,00,06,00 DFB 04,00,02,00 DFB 00,00,00,04,08,04 DFB 08,06,08,08,08,10,08,20 LETTER_U DFB 00,20,00,18,00,16,00,14,00,12,00,10 DFB 00,07,07,00,10,00 DFB 10,04,05,09,05,16,17,16 DFB 17,00,22,00,22,20,20,20,18,20,16,20,14,20,12,20,10,20 DFB 00,20 LETTER_V DFB 07,20,00,13,00,00,05,00 DFB 05,12,09,16,13,16,17,12 DFB 17,00,22,00,22,02,22,04,22,06,22,08,22,10 DFB 22,13,15,20,13,20,11,20,09,20,07,20 DFB 07,20 LETTER_W DFB 00,20,05,20,10,15,12,15 DFB 17,20,22,20,22,00,17,00 DFB 17,14,16,14,12,10,10,10 DFB 06,14,05,14,05,08,10,03 DFB 10,00,07,00,00,07,00,09,00,11,00,20 LETTER_X DFB 00,20,00,19,08,11,08,09 DFB 00,01,00,00,05,00,11,06 DFB 17,00,22,00,22,01,14,09 DFB 14,11,22,19,22,20,17,20 DFB 11,14,05,20,04,20,03,20,02,20,00,20 LETTER_Y DFB 09,20,14,20,14,14,16,14,18,14,20,14 DFB 22,14 DFB 22,00,17,00,17,10,15,10,13,10,11,10,05,10 DFB 05,09,10,04,10,00,07,00 DFB 00,07,00,14,09,14,09,20 LETTER_Z DFB 00,20 DFB 00,18,14,04,00,04 DFB 00,00,02,00,04,00,06,00,08,00,10,00,12,00,14,00,16,00,18,00 DFB 20,00 DFB 22,00,22,03,09,16 DFB 22,16,22,20,20,20,00,20 SPACE DFB 01,05,03,05,05,05,07,05,09,05,11,05,13,05,15,05,17,05 DFB 19,05,20,05,21,05 DFB 22,05,22,07,22,09,22,11 DFB 22,13,01,13,01,11,01,09,01,07,01,05 ; ; LETTER_ADDR - Word pointers to construction table ; LETTER_ADDR DFW LETTER_A DFW LETTER_B DFW LETTER_C DFW LETTER_D DFW LETTER_E DFW LETTER_F DFW LETTER_G DFW LETTER_H DFW LETTER_I DFW LETTER_J DFW LETTER_K DFW LETTER_L DFW LETTER_M DFW LETTER_N DFW LETTER_O DFW LETTER_P DFW LETTER_Q DFW LETTER_R DFW LETTER_S DFW LETTER_T DFW LETTER_U DFW LETTER_V DFW LETTER_W DFW LETTER_X DFW LETTER_Y DFW LETTER_Z DFW SPACE ; ; SPRTAB - Sprite table locations ; SPRTAB DFW $CC00 DFW $CC00+64 DFW $CC00+128 LETTER_NUM DFB 0 SPRNUM DFB 0 ATAB DFS POINTS*2,0 ; Construction point stores BTAB DFS POINTS*2,0 MUTCOUNT DFB 0 XPOS DFB 82+100,110+100,138+100 DFB 82+100,110+100,138+100 SCORE_LINE DFB 0 COLTAB DFB 1,1,1,6,6,6 ; ; Buffered line coordinates ; X1 DFS POINTS*2,0 ; X & Y from to line coordinates X2 DFS POINTS*2,0 Y2 DFS POINTS*2,0 X1A DFS POINTS*2,0 ; X & Y mutation line coordinates X2A DFS POINTS*2,0 Y2A DFS POINTS*2,0 ; ; Indexes into sprite ; YTAB DFB 0,3,6,9,12,15,18 DFB 21,24,27,30,33,36,39 DFB 42,45,48,51,54,57,60 XTAB DFB 128,64,32,16,8,4,2,1 DFB 128,64,32,16,8,4,2,1 DFB 128,64,32,16,8,4,2,1 XOFF DFB 0,0,0,0,0,0,0,0 DFB 1,1,1,1,1,1,1,1 DFB 2,2,2,2,2,2,2,2 LETTERPOS DFB 0 LETTER DFB 0 JOY_TEMP DFB 0 DEBOUNCE DFB 0 ; Fire Debounce flag ASCII DFM "ABCDEFGHIJKLMNOPQRSTUVWXYZ " ; ; MUTATE_IT - Initialises the mutator ; MUTATE_IT LDX #1+2+4+8+16+32 STX $D015 LDX #0 STX SPRNUM STX LETTERPOS STX DEBOUNCE STX $D01B STX $D01C ; Sprite multi-colour disable LDY #0 SET_SPRITES LDA XPOS,X STA $D000,Y LDA #123+80 STA $D001,Y LDA COLTAB,X STA $D027,X INY INY INX CPX #6 BNE SET_SPRITES LDX #63 LDA #$FF ; Make a filled sprite pointer FILL_SPR STA $C000+$33*64,X DEX BPL FILL_SPR LDY #$30 ; Init sprite pointers STY $CBF8 INY STY $CBF9 INY STY $CBFA INY STY $CBFB STY $CBFC STY $CBFD DUMP_INITIAL LDA #SPACE ; Initialise all sprites to space STA FROMM STA TO LDA ^SPACE STA FROMM+1 STA TO+1 JSR CLR_BUFFER JSR TRANSFER1 JSR LINE_DRAW INC SPRNUM INC SPRNUM LDA SPRNUM CMP #6 BNE DUMP_INITIAL LDX #26 STX LETTER LDA #0 STA SPRNUM JSR FADE_IN ; Fade the character set in LDA #SPACE STA FROMM STA TO LDA ^SPACE STA FROMM+1 STA TO+1 ; ; READ_JOY - Reads the joystick for entering player names ; READ_JOY JSR FX19 LDA $DC00 EOR #$FF AND #$1F STA JOY_TEMP AND #4 BEQ NO_LEFT JMP DOWN_ONE NO_LEFT LDA JOY_TEMP AND #8 BEQ NO_RIGHT JMP UP_IT NO_RIGHT LDA $DC00 AND #$10 BEQ FIRE_PRESS LDA #0 STA DEBOUNCE JMP READ_JOY ; ; ; FIRE_PRESS LDA DEBOUNCE BEQ CAN_GO JMP READ_JOY CAN_GO LDA #1 STA DEBOUNCE INC SPRNUM INC SPRNUM INC LETTERPOS LDA SPRNUM CMP #6 BEQ ALL_DONE LDA #SPACE STA FROMM LDA ^SPACE STA FROMM+1 LDA #26 STA LETTER JMP READ_JOY ALL_DONE JMP BUFFER_SCORES ; Buffer scores in highscore scroll ; DOWN_ONE LDA LETTER BEQ RES_26 DEC LETTER JMP TWIST_IT RES_26 LDA #26 STA LETTER JMP TWIST_IT UP_IT LDA LETTER CMP #26 BEQ RES_ZERO INC LETTER JMP TWIST_IT RES_ZERO LDA #0 STA LETTER ; ; TWIST_IT - Mutates the source letter to the destination letter ; TWIST_IT LDA LETTER TAX ASL STA LETTER_NUM LDY LETTERPOS LDA ASCII,X STA (SCX),Y ORA #$80 SCREEN_ADDR STA $FFFF,Y ; Self Modified LDY LETTER_NUM ; Destination letter LDA LETTER_ADDR,Y STA TO LDA LETTER_ADDR+1,Y STA TO+1 JSR TRANSFER1 ; Copy data for object and target MAINLOOP JSR CLR_BUFFER ; Clear the buffer JSR LINE_DRAW ; Draw the lines required JSR MUTATE ; Mutate the lines JSR CHECKOVER ; Check if mutation is complete BCC MAINLOOP LDA TO ; Make the destination letter STA FROMM LDA TO+1 ; the new source letter STA FROMM+1 JMP READ_JOY ; and back to the joystick read loop. ; ; CLR_BUFFER - clear workspace buffer out ; CLR_BUFFER LDX #63 LDA #0 CLRSP STA BUFFER,X DEX BPL CLRSP RTS ; ; LINE - passes line constructions and plots the lines ; LINE_DRAW LDX #0 ; Pass on the line constructions LINLOP LDA ATAB,X STA XP INX LDA ATAB,X STA YP INX LDA ATAB,X STA XP+1 INX LDA ATAB,X STA YP+1 DEX STX TEMP3 LDA XP+1 ; Caclulate the gradient SUB XP STA XD LDA YP+1 SUB YP STA YD LDA #1 STA A00 STA A1O LDA YD BPL MINUSY ; Positive direction LDY #$FF STY A00 EOR #$FF ADD #1 MINUSY STA YE LDA XD BPL MINUSX LDY #$FF STY A1O EOR #$FF ADD #1 MINUSX STA XE LDA XE SUB YE STA D11 BPL DRAW2 LDA #$FF STA S0 LDA #0 STA S1 LDA YE STA LG LDA XE STA SH LDA YD BMI DRAW1 LDA #1 STA S0 DRAW1 JMP DRAW5 ; Weight the line in X & Y DRAW2 LDA #0 STA S0 LDA #$FF STA S1 LDA XE STA LG LDA YE STA SH DRAW3 LDA XD BMI DRAW5 LDA #1 STA S1 DRAW5 LDA LG STA TTO SUB SH STA UD LDA SH STA TS LSR LG LDA SH SUB LG STA CT2 DRAW7 LDX XP LDY YP JSR PLOT ; Plot each point of the line LDA CT2 BPL ANG2 ADD TS ; Re-weight the line STA CT2 LDA XP ADD S1 STA XP LDA YP ADD S0 STA YP ANG1 JMP ANG3 ANG2 SUB UD STA CT2 LDA XP ADD A1O STA XP LDA YP ADD A00 STA YP ANG3 DEC TTO ANG4 BMI RETURN JMP DRAW7 RETURN LDX TEMP3 CPX #POINTS*2 ; Continue until all lines are done BEQ PLOTTED_IT JMP LINLOP PLOTTED_IT LDY SPRNUM ; Get present sprite address LDA SPRTAB,Y STA DUMP_LOC+1 LDA SPRTAB+1,Y STA DUMP_LOC+2 LDX #63 ; Dump the buffer to the sprite DUMP_IT LDA BUFFER,X DUMP_LOC STA $FFFF,X DEX BPL DUMP_IT RTS PLOT LDA #BUFFER ; Build a line in the buffer STA SPRITE LDA ^BUFFER STA SPRITE+1 LDA SPRITE ADD YTAB,Y STA SPRITE BCC SKIP_CAR INC SPRITE+1 SKIP_CAR LDY XOFF,X LDA (SPRITE),Y ORA XTAB,X STA (SPRITE),Y RTS TRANSFER1 LDY #POINTS*2-1 ; Transfer the construction lines TRANSDAT LDA (FROMM),Y ; into mutatable (!) data STA ATAB,Y LDA (TO),Y STA BTAB,Y DEY BPL TRANSDAT RTS MUTATE LDA #0 STA MUTCOUNT ; Make point comparisons TAX ; and alter point table accordingly MUTATEX1 LDA ATAB,X CMP BTAB,X BEQ LINE_MET BCS SHRINK BCC GROW LINE_MET INC MUTCOUNT BACKX1 INX CPX #POINTS*2 BNE MUTATEX1 RTS ; SHRINK DEC ATAB,X JMP BACKX1 ; GROW INC ATAB,X JMP BACKX1 ; ; CHECKOVER - checks for end of mutation ; CHECKOVER LDA MUTCOUNT CMP #POINTS*2 BEQ ALDUN CLC RTS ALDUN SEC ; Carry set = mutation over RTS ; KEYTAB DFB 10,28,20,18,14,21,26,29,33,34,37,42,36,39,38,41,62 DFB 17,13,22,30,31,9,23,25,12,60 KEYSCAN STY KEYT PHA LSR LSR LSR TAY LDA COLOM,Y STA $DC00 PLA AND #$07 TAY LDA $DC01 AND KROW,Y BNE NOTPRESS LDA #$FF STA $DC00 LDA $DC01 AND KROW,Y BEQ NOTPRESS SEC JMP GOTKEY NOTPRESS CLC GOTKEY LDY KEYT LDA #$FF STA $DC00 LDA #127 STA $DC01 TYA RTS ; KEYT DFB 0 COLOM DFB $FE,$FD,$FB,$F7,$EF,$DF,$BF,$7F KROW DFB $01,$02,$04,$08,$10,$20,$40,$80 ; ; FX19 - Wait for frame flyback ; FX19 LDA LASTCOUNT CMP LASTVAL BEQ FX19 STA LASTVAL RTS LASTCOUNT DFB 0 LASTVAL DFB 0 ; ; WAIT - Wait for the number of frames held in X ; WAIT JSR FX19 DEX BNE WAIT RTS ; ; HALT - Same as wait but will exit if FIRE is pressed. Used during TITLE_LOOP ; HALT JSR FX19 LDA $DC00 AND #$10 BEQ IS_PRESS DEX BNE HALT RTS IS_PRESS PLA ; Unstack last call PLA JMP GAME_INIT ; ; GEN_STARFIELD - This generates the star plotting matrix ; GEN_STARFIELD LDA #0 ; This bit is ignored by the title TAX CLR_SET STA $C000+$E5*8,X INX CPX #26*8 BNE CLR_SET INIT_MATRIX JSR FX19 LDX #$27 ; Called within the title loop DUMP_ROW1 LDA FIRST_ROW,X ADD #$E5 STA $C800,X DEX DEX DEX BPL DUMP_ROW1 LDA #$C800 STA FROMM+0 LDA ^$C800 STA FROMM+1 LDA #$C828 STA TO+0 LDA ^$C828 STA TO+1 LDX #$17 NEXT_ROW LDY #$27 BUILD_MATRIX LDA (FROMM),Y ADD #1 CMP #$FF BEQ RESET_COLUMN DUMP_ON STA (TO),Y LDA #$40 DEY STA (TO),Y DEY STA (TO),Y DEY STA (TO),Y BPL BUILD_MATRIX LDA FROMM ADD #40 STA FROMM BCC PASS_1 INC FROMM+1 PASS_1 LDA TO ADD #40 STA TO BCC PASS_2 INC TO+1 PASS_2 DEX BPL NEXT_ROW LDX #7 PLACE_WINDOW LDA WINDOW_DATA,X ; Print the scrolling window STA $C800+00*40+32,X STA $C800+00*40+00,X LDA #8 STA $D800+00*40+32,X ; Colour it in ( White ) STA $D800+00*40+00,X DEX BPL PLACE_WINDOW RTS ; WINDOW_DATA DFB $DC,$DD,$DE,$DF,$E0,$E1,$E2,$E3 ; RESET_COLUMN LDA #$E5 JMP DUMP_ON ; ; FIRST_ROW - The initial characters used to build the star matrix ; FIRST_ROW DFB 01,$26,$26 DFB 06,$26,$26 DFB 12,$26,$26 DFB 08,$26,$26 DFB 22,$26,$26 DFB 11,$26,$26 DFB 14,$26,$26 DFB 08,$26,$26 DFB 19,$26,$26 DFB 02,$26,$26 DFB 18,$26,$26 DFB 03,$26,$26 DFB 07,$26,$26 DFB 25 ; ; STAR_FIELD - This masks all the stars into the star matrix ; STAR_FIELD LDY #PARALLAX-1 MOVE_STARS LDA STAR_DEL,Y TAX LDA $C000+$E5*8,X AND STAR_MASK,Y STA $C000+$E5*8,X LDA STAR_PRINT,Y STA STAR_DEL,Y TAX LDA $C000+$E5*8,X ORA STAR_DAT,Y STA $C000+$E5*8,X LDA STAR_PRINT,Y ADD SPEED,Y CMP #$D0 BCS REDO SAVE_IT STA STAR_PRINT,Y DEY BPL MOVE_STARS RTS REDO SUB #$D0 JMP SAVE_IT ; PARALLAX EQU 4 STAR_PRINT DFB $08,$20,$60,$90 STAR_DEL DFB $08,$20,$60,$90 SPEED DFB 3,2,1,1 STAR_DAT DFB %11000000 DFB %00010000 DFB %10000000 DFB %00010000 STAR_MASK DFB %00111111 DFB %11101111 DFB %01111111 DFB %11101111 ; ; DERES - Fades the work charcter set out ; DERES LDA #63 STA BIT_COUNT LDA #$C0 STA TO+1 LDA #0 STA TO STA CHAR_COUNT FADE_LOOP LDX BIT_COUNT LDA FADE_X,X STA X_BIT LDA FADE_Y,X TAY LDX X_BIT RID_BIT LDA (TO),Y AND MASK,X STA (TO),Y LDA TO ADD #8 STA TO BCC MISS_1 INC TO+1 MISS_1 INC CHAR_COUNT LDA CHAR_COUNT CMP #$DB BNE RID_BIT LDA #0 STA TO STA CHAR_COUNT LDA #$C0 STA TO+1 DEC BIT_COUNT BPL FADE_LOOP RTS ; ; FADE_IN - This fades a charcter set from $1000 to the work character set ; FADE_IN LDA #63 STA BIT_COUNT LDA #$C0 STA TO+1 CHAR_BASE LDA #$05 STA FROMM+1 LDA #0 STA TO STA FROMM STA CHAR_COUNT FADE_LOOP_2 LDX BIT_COUNT LDA FADE_X,X STA X_BIT LDA FADE_Y,X TAY LDX X_BIT PUT_BIT LDA (FROMM),Y AND MASK_2,X ORA (TO),Y STA (TO),Y LDA FROMM ADD #8 STA FROMM BCC MISS_2 INC FROMM+1 MISS_2 LDA TO ADD #8 STA TO BCC MISS_3 INC TO+1 MISS_3 INC CHAR_COUNT LDA CHAR_COUNT CMP #$DB BNE PUT_BIT LDA #0 STA CHAR_COUNT STA TO STA FROMM LDA #$C0 STA TO+1 CHAR_BASE_2 LDA #$05 STA FROMM+1 DEC BIT_COUNT BPL FADE_LOOP_2 RTS ; ; TRENDY_CLEAR - A trendy way of clearing the screen ! ; TRENDY_CLEAR LDA #0 STA CHAR_COUNT STA FROM LDA #$C0 STA FROM+1 LDA #7 ; 8 Shifts STA BIT_COUNT TRENDY_LOOP JSR FX19 NEXT_TREND LDY #15 PICK_CHAR LDA (FROM),Y LSR STA (FROM),Y DEY CPY #7 BNE PICK_CHAR PICK_CHAR_2 LDA (FROM),Y ASL STA (FROM),Y DEY BPL PICK_CHAR_2 LDA FROM ADD #16 STA FROM BCC BOUND_1 INC FROM+1 BOUND_1 INC CHAR_COUNT LDA CHAR_COUNT CMP #$6F BNE NEXT_TREND LDA #0 STA CHAR_COUNT STA FROM LDA #$C0 STA FROM+1 DEC BIT_COUNT BPL TRENDY_LOOP RTS ; CHAR_COUNT DFB 0 BIT_COUNT DFB 0 X_BIT DFB 0 MASK DFB %01111111 DFB %10111111 DFB %11011111 DFB %11101111 DFB %11110111 DFB %11111011 DFB %11111101 DFB %11111110 MASK_2 DFB 128,64,32,16,8,4,2,1 FADE_X DFB 3,7,2,5,7,3,0,0,5,4,3,1,1,5,2 DFB 4,6,0,0,7,5,3,5,6,2,3,7,2,2,7 DFB 0,5,2,2,5,4,6,7,1,4,5,6,6,7 DFB 0,2,4,3,0,3,6,6,7,6,4,4,1 DFB 1,0,3,1,4,1,1 FADE_Y DFB 2,2,6,4,6,0,2,3,1,6,4,4,5,7,2 DFB 3,1,0,7,4,6,7,2,5,0,5,5,7,3,1 DFB 4,3,4,1,0,4,3,3,1,5,5,4,7,0 DFB 5,5,1,3,6,1,6,0,7,2,2,0,2 DFB 7,1,6,0,7,6,3 ; ; SPRINT - Print text pointed to by X & Y in single or double height ; SPRINT STX FROM2 STY FROM2+1 GET LDY #0 LDA (FROM2),Y BMI GETCOORD BNE TEXT JMP DONE_IT TEXT LDX MODE_BYTE BNE DUBUL AND #$3F ORA #$80 STA (TO),Y LDA CULA STA (TO2),Y INC TO BNE NOC2 INC TO+1 NOC2 INC TO2 BNE NOC3 INC TO2+1 NOC3 INC FROM2 BNE GET INC FROM2+1 JMP GET DUBUL AND #$3F ASL STA (TO),Y TAX LDA CULA STA (TO2),Y INY INX TXA STA (TO),Y LDA CULA STA (TO2),Y LDA TO ADD #2 STA TO STA TO2 BCC NOC3 INC TO+1 INC TO2+1 JMP NOC3 GETCOORD AND #$7F STA MODE_BYTE ; Set printing mode (single or double) INY ; Get data; X coord, Y coord, colour LDA (FROM2),Y STA TEMP INY LDA (FROM2),Y ASL TAX LDA TEMP ADD YTABLE,X STA TO STA TO2 LDA YTABLE+1,X ADC #0 STA TO+1 ADC #$D8-$C8 STA TO2+1 INY LDA (FROM2),Y STA CULA LDA FROM2 ADD #4 STA FROM2 BCC NO_C INC FROM2+1 NO_C LDY #0 JMP GET DONE_IT RTS ; CULA DFB 0 MODE_BYTE DFB 0 YTABLE DFW $C800+00*40 DFW $C800+01*40 DFW $C800+02*40 DFW $C800+03*40 DFW $C800+04*40 DFW $C800+05*40 DFW $C800+06*40 DFW $C800+07*40 DFW $C800+08*40 DFW $C800+09*40 DFW $C800+10*40 DFW $C800+11*40 DFW $C800+12*40 DFW $C800+13*40 DFW $C800+14*40 DFW $C800+15*40 DFW $C800+16*40 DFW $C800+17*40 DFW $C800+18*40 DFW $C800+19*40 DFW $C800+20*40 DFW $C800+21*40 DFW $C800+22*40 DFW $C800+23*40 DFW $C800+24*40 AT EQU $80 DW EQU $81 ; ; TUNE - Initialises a tune, entered with tune number in X ; TUNE LDY #0 LDA #0 CLR_VAR STA VAR_START,Y ; Reset all variables to zero INY CPY #VAR_END-VAR_START BNE CLR_VAR LDY #$16 CLRSID LDA #8 ; Set SID test bit so there's no STA SID,Y LDA #0 ; grotty clicking STA SID,Y DEY BPL CLRSID STY MODEBYTE_A ; Reset any non-zero variables ($FF) STY MODEBYTE_B STY MODEBYTE_C LDY #1 STY DURCOUNT.A ; $01 STY DURCOUNT.B STY DURCOUNT.C STY DURATIONON_A STY DURATIONON_B STY DURATIONON_C STY MFL_A STY MFL_B STY MFL_C LDA TUNETABLE.A.L,X ; Initialise the addresses STA PC.A LDA TUNETABLE.A.H,X ; of the tunes into each STA PC.A+1 LDA TUNETABLE.B.L,X ; individual program counter STA PC.B LDA TUNETABLE.B.H,X STA PC.B+1 LDA TUNETABLE.C.L,X STA PC.C LDA TUNETABLE.C.H,X STA PC.C+1 LDA #$00 ; CHECK FOR TITLE TUNE CPX #2 ; BEQ MISSFULLVOL ; LDA #$0F ; Volume on MISSFULLVOL STA $D418 RTS ; Finito ; ; REFRESH - Called by interrupt, plays the music ; REFRESH LDA MFL_A ; Check if channel A is playing BEQ NOMUSIC_A JSR MUSICA ; Play it NOMUSIC_A LDA MFL_B ; Check if channel B is playing BEQ NOMUSIC_B JSR MUSICB ; Play it NOMUSIC_B LDA MFL_C ; Check if channel C is playing BEQ NOMUSIC_C JSR MUSICC ; Play it NOMUSIC_C LDA #READ_C ; Set up the channel C indirect STA MOD_1+1 ; address for the arpeggio LDA #2 ; Start modulation from channel C STA VOICE_NUM LDX VOICE_NUM NEXT_VOICE LDA drumFLAG,X ; If a drum is playing don't do any BNE NORND_A ; modulators LDA ARPFLAG_A,X ; Is the arpeggio active on this BEQ NOAR_A ; Voice JSR DO_ARP_A ; Yes, process the arpeggio NOAR_A LDA PULSEFLAG_A,X ; Is the pulse width active on this BEQ NOPUL_A ; voice JSR DOPULSE_A ; Yes, process the pulse width NOPUL_A LDA RNDFLAG_A,X BEQ NORND_A JSR DOSHPWM_A NORND_A DEC MOD_1+1 ; Modify the indirect arpeggio address DEC MOD_1+1 DEX STX VOICE_NUM ; Do the next voice BPL NEXT_VOICE NOPUL_C JMP DRUMMER ; Process DunnyDrums (tm) ; ; MUSICTEST - Tests to see if music is playing ; MUSICTEST LDA MFL_A ; ORA all the flags together ORA MFL_B ; if zero is the result then the ORA MFL_C ; tune is complete RTS ; ; MUSICA - Handles all music to channel A ; MUSICA DEC DURCOUNT.A ; Note duration over ? BEQ READBYTE.A ; Yup, get a new byte DEC RELEASE_A ; Has the note release finished BNE NO_RELEASE_A ; No, modulate channel A LDA EFFECTFLAG_A ; Effect mode active ? BEQ NOEFFECT_A ; No LDX REAL_NOTE_A ; Get the real unmauled note LDA LOWFREQ,X STA FREQ.LOW.A ; expand out into a frequency LDA HIFREQ,X STA FREQ.HI.A NOEFFECT_A LDA MODEBYTE_A ; Should the gate get set AND #1 BEQ NO_RELEASE_A ; No way jose LDA GATEOFF.A ; Set the gate bit STA $D404 NO_RELEASE_A LDX #0 JMP MODULATE ; Modulate channel A READBYTE.A LDA SUSTAIN_A ; Reset the note's release period STA RELEASE_A LDY #0 ; Shut down any drum on this channel STY drumFLAG+0 LDA (PC.A),Y ; Get next byte from the data BPL NOCONTROL_A TAX LDA JUMPVECL.A-128,X ; the control code vectors STA JUMPVEC.A+1 LDA JUMPVECH.A-128,X STA JUMPVEC.A+2 INY JUMPVEC.A JMP $FFFF ; Self modified jump address NOCONTROL_A CMP #REST ; Is it a rest BNE NOREST_A JMP REST_A ; Yes process a rest NOREST_A ADD TRANSVAL_A ; Add any transpose value to the base STA NOTE_A ; note, and store it STA REAL_NOTE_A LDX EFFECTFLAG_A ; Is effect mode enabled BEQ NOFX_A ; No, thank God ! LDA MODEBYTE_A ; Is it an emulated plucked note (!) AND #8 BNE PLUCK ; Yessum boss LDA EFFECT_NOTE_A ; Use the effect note for the freq JMP NOFX_A PLUCK LDA REAL_NOTE_A ; Otherwise get the base note and ADD EFFECT_NOTE_A ; add the effect note on NOFX_A TAX ; Expand the note into a frequency LDA LOWFREQ,X STA FREQ.LOW.A ; Maulable frequencys LDA HIFREQ,X STA FREQ.HI.A DOREST_A LDA PULSEFLAG_A ; Pulse mode enabled ? BEQ NOPULSE_A ; No LDA MODEBYTE_A ; Should the pulse be retriggered AND #2 BEQ NOPULSE_A ; No LDA PWL2_A ; Reset all pulse width variables STA PWL_A LDA PWH2_A STA PWH_A LDA #0 STA PULSEDIR_A ; Pulse direction LDA CUP2_A ; Counts up STA CUP_A LDA CDOWN2_A ; Counts down STA CDOWN_A NOPULSE_A LDA VIBFLAG_A ; Is the vibrato active BEQ NOV_A ; No LDA VIBDELAY2_A ; Reset the vibrato delay STA VIBDELAY_A LDA VIBDEPTH_A ; Get the vibrato depth LSR STA VIBDEPTH2_A ; Divide it by 2 for other direction LDA #0 ; Reset the Vib direction variable STA VIB_DIR_A NOV_A LDA MODEBYTE_A ; Should the gate get set AND #1 BEQ REST_A ; No LDA GATE.A ; Set the gate bit STA $D404 REST_A LDA GLISSFLAG_A ; Should glissando be cancelled BMI NORESET_A ; No LDA #0 ; Mask off bit 7 STA GLISSFLAG_A NORESET_A LDA DURATIONON_A ; Automatic duration mode ? BNE PICK_UP_A ; No LDA DURATION_A ; Reset the note duration STA DURCOUNT.A LDX GAPFLAG_A ; Gap mode active BEQ NOGAP2_A ; no SUB SUSTAIN_A ; Subtact the sustain from the STA RELEASE_A ; duration to give a release value NOGAP2_A INC PC.A ; Increment the music PC BNE COMEOUT.A INC PC.A+1 COMEOUT.A JMP NO_RELEASE_A ; Do the modulators for channel A PICK_UP_A INY ; Manual duration mode LDA (PC.A),Y STA DURCOUNT.A ; Get the duration of the note LDX GAPFLAG_A ; Gap mode active BEQ NOGAP_A ; No SUB SUSTAIN_A ; Subtact the sustain from the STA RELEASE_A ; duration to give a release value NOGAP_A LDA PC.A ; Add 2 to the music PC ADD #2 STA PC.A BCC SKIPIT_A INC PC.A+1 SKIPIT_A JMP NO_RELEASE_A ; Do the modulators for channel A ; ; MODULATE - Handles all modulation requirements for Channels A,B & C ; MODULATE LDA ARPFLAG_A,X ; Is arpeggio processing BEQ NOARP_A FORGETIT RTS ; Yes, don't bother with other stuff NOARP_A LDA drumFLAG,X ; Is drum playin ? BNE FORGETIT ; Yes LDA GLISSFLAG_A,X ; Glissando on ? BEQ NOGLISS.A ; No JSR DO_GLISS_A ; Do glissando stuff and nowt else LDA GLISSFLAG_A,X ; Allow modulators to run during BMI NOGLISS.A ; glissando count it JMP DUMP NOGLISS.A LDA PORTFLAG.A,X ; Pitch bender on ? BEQ NOBEND.A ; No JSR DO.BEND.A ; Set up a pitch bend and nowt else JMP DUMP NOBEND.A LDA VIBFLAG_A,X ; Is the vibrato active ? BEQ NOVIB_A ; No JSR DOVIB_A ; Process the vibrato NOVIB_A JMP DUMP ; Dump the final frequency to SID ; ; DO_GLISS_A - Processes all glissando to all channels ; DO_GLISS_A LDA GLISSCOUNT_A,X ; Time to do glissando ? BEQ GO_GLISS DEC GLISSCOUNT_A,X ; No, decrement the counter RTS ; Exit GO_GLISS LDA #1 STA GLISSFLAG_A,X ; Allow glissando to be cancelled LDA GLISSDIR_A,X ; Get the glissando direction BMI GLISS_DOWN GLISS_UP LDA FREQ.LOW.A,X ; Glissando up ADD GLISSRATE_A,X STA FREQ.LOW.A,X ; Add the rate to the frequency BCC NO_CARRY INC FREQ.HI.A,X NO_CARRY RTS GLISS_DOWN LDA FREQ.LOW.A,X ; Glissando down SUB GLISSRATE_A,X STA FREQ.LOW.A,X ; Subtract the rate from the frequency BCS NO_CARRY_2 DEC FREQ.HI.A,X NO_CARRY_2 RTS ; ; DO.BEND.A - Processes all pitchbending to all channels ; DO.BEND.A BMI SET.BEND.A ; Bendflag minus = init bend DEC BENDLENGTH.A,X ; See if bend complete BEQ BEND.DONE.A ; Exit if so PROC.BEND.A LDA BEND.DIR.A,X ; Otherwise get bend direction BMI BEND.DOWN.A ; Minus = downwards bend LDA FREQ.LOW.A,X ; Get frequency and add the bend ADD BENDSTEP.A,X STA FREQ.LOW.A,X ; additive BCC NOCHANGE1.A INC FREQ.HI.A,X NOCHANGE1.A RTS ; Exit BEND.DOWN.A LDA FREQ.LOW.A,X ; Get frequency and subtract the bend SUB BENDSTEP.A,X STA FREQ.LOW.A,X ; subtractive BCS NOCHANGE2.A DEC FREQ.HI.A,X NOCHANGE2.A RTS ; Exit BEND.DONE.A LDA #0 ; Terminate the pitchbend STA PORTFLAG.A,X RTS ; Exit SET.BEND.A LDA #1 ; Do bend but don't re-initialise STA PORTFLAG.A,X LDY WORD_OFFSET,X LDA BEND.DIR.A,X ; Get the bend direction BMI SET.DOWN.A LDA FREQ.LOW.A,X ; Subract the offset from the base SUB OFFSET.A,Y STA FREQ.LOW.A,X ; frequency (bend up to a note) LDA FREQ.HI.A,X SBC OFFSET.A+1,Y STA FREQ.HI.A,X JMP PROC.BEND.A ; Process the bend SET.DOWN.A LDA FREQ.LOW.A,X ; Add the offset from the base ADD OFFSET.A,Y STA FREQ.LOW.A,X ; frequency (bend down to a note) LDA FREQ.HI.A,X ADC OFFSET.A+1,Y STA FREQ.HI.A,X JMP PROC.BEND.A ; Process the bend ; ; DOVIB_A - Suprisingly enuf this handles the vibrato ; DOVIB_A LDA VIBDELAY_A,X ; Time to activate the vibrato BEQ DELAYOFF_A DEC VIBDELAY_A,X ; No, not yet RTS DELAYOFF_A DEC VIBDEPTH2_A,X ; Decrement the vib direction counter BEQ CHANGEDIR_A ; Zero = change the direction LDA VIB_DIR_A,X ; Get the vibrato direction BNE VIB_DOWN_A LDA FREQ.LOW.A,X ; Get the base frequency ADD VIBRATE_A,X ; Add the vibrato add rate STA FREQ.LOW.A,X BCC NOADD_A INC FREQ.HI.A,X NOADD_A RTS ; Exit VIB_DOWN_A LDA FREQ.LOW.A,X ; Get the base frequency SUB VIBRATE_A,X ; Subtract the vibrato subtract rate STA FREQ.LOW.A,X BCS NOADD2_A DEC FREQ.HI.A,X NOADD2_A RTS ; Exit CHANGEDIR_A LDA VIB_DIR_A,X ; Flip the vibrato direction EOR #1 STA VIB_DIR_A,X LDA VIBDEPTH_A,X ; Reset the depth counter STA VIBDEPTH2_A,X JMP DELAYOFF_A ; Back to processing the vibrato ; ; TRANS_A - Constant transpose value initialise ; TRANS_A LDA (PC.A),Y ; Pull in the transpose value STA TRANSVAL_A ; Store it LDA #2 JMP ADD_PC_A ; Bump the PC ; ; TRANS_B - Constant transpose value initialise ; TRANS_B ; Ditto LDA (PC.B),Y STA TRANSVAL_B LDA #2 JMP ADD_PC_B ; ; TRANS_C - Constant transpose value initialise ; TRANS_C ; Ditto LDA (PC.C),Y STA TRANSVAL_C LDA #2 JMP ADD_PC_C ; ; CT_A - Call a routine transposed ; CT_A LDA (PC.A),Y ; Pull in the transpose value STA TRANSVAL_A ; Store INC PC.A ; Bump the PC BNE SKPCT_A INC PC.A+1 SKPCT_A JMP CALL.A ; Cheap n nasty go to the CALL routine ; ; CT_B - Call a routine transposed ; CT_B ; Ditto LDA (PC.B),Y STA TRANSVAL_B INC PC.B BNE SKPCT_B INC PC.B+1 SKPCT_B JMP CALL.B ; ; CT_C - Call a routine transposed ; CT_C ; Ditto LDA (PC.C),Y STA TRANSVAL_C INC PC.C BNE SKPCT_C INC PC.C+1 SKPCT_C JMP CALL.C ; ; LENGTH_A - Determines the duration of the notes ; LENGTH_A LDA (PC.A),Y ; Pull in the constant duration value STA DURATION_A LDA #0 STA DURATIONON_A ; Signal this mode LDA #2 JMP ADD_PC_A ; Bump the PC ; ; DO_ARP_A - Processes the arpeggiator on A,B & C ; DO_ARP_A DEC NEXTDELAY_A,X ; Time to read the next byte yet ? BEQ GO_ARP_A RTS ; No GO_ARP_A LDA NEXTDELAY2_A,X ; Reset the read period STA NEXTDELAY_A,X LDY ARPEGIND_A,X ; Get the index within the table MOD_1 LDA (READ_A),Y ; plus the indirect address LDY SID_OFFSETS,X ADD NOTE_A,X ; add this value to the base note TAX LDA LOWFREQ,X ; Expand out into a frequency STA $D400,Y LDA HIFREQ,X STA $D401,Y LDX VOICE_NUM INC ARPEGIND_A,X ; Increment the index within the table LDA ARPEGIND_A,X CMP ARPEGLEN_A,X ; Reached the end of the table yet ? BNE RESETARP_A LDA #2 ; Yes reset the index to 2 STA ARPEGIND_A,X RESETARP_A RTS ; Exit ; ; DOPULSE_A - Process pwm on A,B & C ; DOPULSE_A LDA PULSEDIR_A,X ; Get the pulse direction BNE PULSEDOWN_A PULSEUP_A DEC CUP_A,X ; Decrement the pulse up counter BEQ NEWDIR_A ; zero, do the other direction LDY SID_OFFSETS,X LDA PWL_A,X ; Add the rate up to the ADD RATEUP_A,X STA PWL_A,X ; pulse width STA $D402,Y LDA PWH_A,X ADC #0 STA PWH_A,X STA $D403,Y RTS ; Exit PULSEDOWN_A DEC CDOWN_A,X ; Decrement the pulse down counter BEQ NEWDIR2_A ; Zero, do the other direction LDY SID_OFFSETS,X LDA PWL_A,X ; Subtract the pulse down counter SUB RATEUP_A,X STA PWL_A,X ; to the pulse width STA $D402,Y LDA PWH_A,X SBC #0 STA PWH_A,X STA $D403,Y RTS ; Exit NEWDIR_A LDA CUP2_A,X ; Reset the count up STA CUP_A,X LDA #1 ; Set the new direction STA PULSEDIR_A,X JMP PULSEDOWN_A ; Process it NEWDIR2_A LDA CDOWN2_A,X ; Reset the count down STA CDOWN_A,X LDA #0 ; Set the new direction STA PULSEDIR_A,X JMP PULSEUP_A ; Process it ; ;DOSHPWM_A - Puts a random number into the Pulse Width register ; DOSHPWM_A LDA RNDDELAY_A,X ;Has delay counted down BEQ DOSH ;Yes DEC RNDDELAY_A,X ;No,so dec it ; DEC $D021 RTS DOSH LDA RNDDELAYR_A,X ;Reset pulse delay STA RNDDELAY_A,X ; LDY SID_OFFSETS,X JSR RND ;Get random number STA $D402,Y ;and store it to pulse lo-byte ;STA PWL_A,X ;*THIS STORE FOR VISUAL PURPOSE ONLY* JSR RND ; STA $D403,Y ;store to pulse hi-byte ;STA PWH_A,X ;*THIS STORE FOR VISUAL PURPOSE ONLY* RTS RND LDA RAN ;Create a random number AND #$70 ; ADC #$12 ASL:ASL ROL RAN+3 ROL RAN+2 ROL RAN+1 LDA RAN ASL EOR $DC04 ADC #$01 STA RAN RTS RAN DFB 255,128,27,52 ;Seed table for random numbers ; ; DUMP - Dumps frequencies to SID channel A,B & C ; DUMP LDY SID_OFFSETS,X LDA FREQ.LOW.A,X ; Get the final mauled frequency STA $D400,Y LDA FREQ.HI.A,X ; and send it to SID STA $D401,Y RTS ; ; ADD_PC_A - Adds a value in A to PC.A ; ADD_PC_A ADD PC.A ; Add PC to the value in the STA PC.A BCC SKP_A ; accumulator INC PC.A+1 SKP_A JMP READBYTE.A ; and back to the sequencer ; ; DUR_ON_A - Acctivates manual duration mode ; DUR_ON_A LDA #1 ; Set the manual duration flag STA DURATIONON_A INC PC.A ; Bump PC BNE SKIP_A INC PC.A+1 SKIP_A JMP READBYTE.A ; Back to the sequencer ; ; PULSEON_A - Switches pulse width modulation on ! ; PULSEON_A LDA #0 STA FROM+1 ; Zero FROM+1 STA RNDFLAG_A ; Turn off random pulse modulation LDA (PC.A),Y ; Get the pulse patch number ASL:ASL ADD (PC.A),Y ; *5 ADC #PWM_START STA FROM LDA FROM+1 ADC ^PWM_START ; plus PWM table base address STA FROM+1 DEY ; Y=0 LDA (FROM),Y STA RATEUP_A ; Get the rate on the upward sweep INY ; Y=1 STY PULSEFLAG_A ; Pulse enabled STY PULSEDIR_A ; Set the initial direction LDA (FROM),Y STA CUP_A ; Get the additive count STA CUP2_A INY LDA (FROM),Y STA CDOWN_A ; Get the subtractive count STA CDOWN2_A INY ; Y=2 LDA (FROM),Y ; Initial pulse width LOW STA PWL2_A INY ; Y=3 LDA (FROM),Y STA PWH2_A ; Initial pulse width HIGH LDA #2 ; Bump PC JMP ADD_PC_A ; ; MUSICB - Handles all music to channel B ; MUSICB DEC DURCOUNT.B BEQ READBYTE.B DEC RELEASE_B BNE NO_RELEASE_B LDA drumFLAG+1 BEQ DOEFFECT_B RTS DOEFFECT_B LDA EFFECTFLAG_B BEQ NOEFFECT_B LDX REAL_NOTE_B LDA LOWFREQ,X STA FREQ.LOW.B LDA HIFREQ,X STA FREQ.HI.B NOEFFECT_B LDA MODEBYTE_B AND #1 BEQ NO_RELEASE_B LDA GATEOFF.B STA $D404+7 NO_RELEASE_B LDX #1 JMP MODULATE ; Modulate channel B READBYTE.B LDA SUSTAIN_B STA RELEASE_B LDA drumFLAG+1 BEQ DONTOFF_B LDA #0 STA drumFLAG+1 STA DRUMx+1 STA $D404+7 LDA SUSTEMP+1 STA $D406+7 LDA ADTEMP+1 STA $D405+7 DONTOFF_B LDY #0 LDA (PC.B),Y BPL NOCONTROL_B TAX LDA JUMPVECL.B-128,X STA JUMPVEC.B+1 LDA JUMPVECH.B-128,X STA JUMPVEC.B+2 INY JUMPVEC.B JMP $FFFF NOCONTROL_B CMP #REST BNE NOREST_B JMP REST_B NOREST_B ADD TRANSVAL_B STA NOTE_B STA REAL_NOTE_B LDX EFFECTFLAG_B BEQ NOFX_B LDA MODEBYTE_B AND #8 BNE PLUCK_B LDA EFFECT_NOTE_A JMP NOFX_B PLUCK_B LDA REAL_NOTE_B ADD EFFECT_NOTE_B NOFX_B TAX LDA LOWFREQ,X STA FREQ.LOW.B ; Maulable frequencys LDA HIFREQ,X STA FREQ.HI.B LDA PULSEFLAG_B BEQ NOPULSE_B LDA MODEBYTE_B AND #2 BEQ NOPULSE_B LDA PWL2_B STA PWL_B LDA PWH2_B STA PWH_B LDA #0 STA PULSEDIR_B LDA CUP2_B STA CUP_B LDA CDOWN2_B STA CDOWN_B NOPULSE_B LDA VIBFLAG_B BEQ NOV_B LDA VIBDELAY2_B STA VIBDELAY_B LDA VIBDEPTH_B LSR STA VIBDEPTH2_B LDA #0 STA VIB_DIR_B NOV_B LDA MODEBYTE_B AND #1 BEQ REST_B LDA GATE.B STA $D404+7 REST_B LDA GLISSFLAG_B BMI NORESET_B LDA #0 STA GLISSFLAG_B NORESET_B LDA DURATIONON_B BNE PICK_UP_B LDA DURATION_B STA DURCOUNT.B LDX GAPFLAG_B BEQ NOGAP2_B SUB SUSTAIN_B STA RELEASE_B NOGAP2_B INC PC.B BNE COMEOUT.B INC PC.B+1 COMEOUT.B JMP NO_RELEASE_B PICK_UP_B INY LDA (PC.B),Y STA DURCOUNT.B LDX GAPFLAG_B BEQ NOGAP_B SUB SUSTAIN_B STA RELEASE_B NOGAP_B LDA PC.B ADD #2 STA PC.B BCC SKIPIT_B INC PC.B+1 SKIPIT_B JMP NO_RELEASE_B ; ; ADD_PC_B - Adds a value in A to PC.B ; ADD_PC_B ADD PC.B STA PC.B BCC SKP_B INC PC.B+1 SKP_B JMP READBYTE.B ; ; LENGTH_B - Determines the duration of the notes ; LENGTH_B LDA (PC.B),Y STA DURATION_B LDA #0 STA DURATIONON_B LDA #2 JMP ADD_PC_B ; ; DUR_ON_B - Acctivates manual duration mode ; DUR_ON_B LDA #1 STA DURATIONON_B INC PC.B BNE SKIP_B INC PC.B+1 SKIP_B JMP READBYTE.B ; ; PULSEON_B - Switches pulse width modulation on ! ; PULSEON_B LDA #0 STA FROM+1 STA RNDFLAG_B LDA (PC.B),Y ASL:ASL ADD (PC.B),Y ADC #PWM_START STA FROM LDA FROM+1 ADC ^PWM_START STA FROM+1 DEY LDA (FROM),Y STA RATEUP_B INY STY PULSEFLAG_B STY PULSEDIR_B LDA (FROM),Y STA CUP_B STA CUP2_B INY LDA (FROM),Y STA CDOWN_B STA CDOWN2_B INY LDA (FROM),Y STA PWL2_B INY LDA (FROM),Y STA PWH2_B LDA #2 JMP ADD_PC_B ; ; MUSICC - Handles all music to channel C ; MUSICC DEC DURCOUNT.C BEQ READBYTE.C DEC RELEASE_C BNE NO_RELEASE_C LDA drumFLAG+2 BEQ DOEFFECT_C RTS DOEFFECT_C LDA EFFECTFLAG_C BEQ NOEFFECT_C LDX REAL_NOTE_C LDA LOWFREQ,X STA FREQ.LOW.C LDA HIFREQ,X STA FREQ.HI.C NOEFFECT_C LDA MODEBYTE_C AND #1 BEQ NO_RELEASE_C LDA GATEOFF.C STA $D404+14 NO_RELEASE_C LDA drumFLAG+2 ; No modulation during drums BEQ DO_MODULATE RTS DO_MODULATE LDX #2 JMP MODULATE ; Modulate channel C READBYTE.C LDA SUSTAIN_C STA RELEASE_C LDA drumFLAG+2 BEQ DONTOFF_C LDA #0 STA drumFLAG+2 STA DRUMx+2 STA $D404+14 LDA SUSTEMP+2 STA $D406+14 LDA ADTEMP+2 STA $D405+14 DONTOFF_C LDY #0 LDA (PC.C),Y BPL NOCONTROL_C ; Found a control byte TAX LDA JUMPVECL.C-128,X STA JUMPVEC.C+1 LDA JUMPVECH.C-128,X STA JUMPVEC.C+2 INY JUMPVEC.C JMP $FFFF NOCONTROL_C CMP #REST BNE NOREST_C JMP REST_C NOREST_C ADD TRANSVAL_C STA NOTE_C STA REAL_NOTE_C LDX EFFECTFLAG_C BEQ NOFX_C LDA MODEBYTE_C AND #8 BNE PLUCK_C LDA EFFECT_NOTE_C JMP NOFX_C PLUCK_C LDA REAL_NOTE_C ADD EFFECT_NOTE_C NOFX_C TAX LDA LOWFREQ,X STA FREQ.LOW.C ; Maulable frequencys LDA HIFREQ,X STA FREQ.HI.C DOREST_C LDA PULSEFLAG_C BEQ NOPULSE_C LDA MODEBYTE_C AND #2 BEQ NOPULSE_C LDA PWL2_C STA PWL_C LDA PWH2_C STA PWH_C LDA #0 STA PULSEDIR_C LDA CUP2_C STA CUP_C LDA CDOWN2_C STA CDOWN_C NOPULSE_C LDA VIBFLAG_C BEQ NOV_C LDA VIBDELAY2_C STA VIBDELAY_C LDA VIBDEPTH_C LSR STA VIBDEPTH2_C LDA #0 STA VIB_DIR_C NOV_C LDA MODEBYTE_C AND #1 BEQ REST_C LDA GATE.C STA $D404+14 REST_C LDA GLISSFLAG_C BMI NORESET_C LDA #0 STA GLISSFLAG_C NORESET_C LDA DURATIONON_C BNE PICK_UP_C LDA DURATION_C STA DURCOUNT.C LDX GAPFLAG_C BEQ NOGAP2_C SUB SUSTAIN_C STA RELEASE_C NOGAP2_C INC PC.C BNE COMEOUT.C INC PC.C+1 COMEOUT.C JMP NO_RELEASE_C PICK_UP_C INY LDA (PC.C),Y STA DURCOUNT.C LDX GAPFLAG_C BEQ NOGAP_C SUB SUSTAIN_C STA RELEASE_C NOGAP_C LDA PC.C ADD #2 STA PC.C BCC SKIPIT_C INC PC.C+1 SKIPIT_C JMP NO_RELEASE_C ; ; LENGTH_C - Determines the duration of the notes ; LENGTH_C LDA (PC.C),Y STA DURATION_C LDA #0 STA DURATIONON_C LDA #2 JMP ADD_PC_C ; ; DUR_ON_C - Acctivates manual duration mode ; DUR_ON_C LDA #1 STA DURATIONON_C INC PC.C BNE SKIP_C INC PC.C+1 SKIP_C JMP READBYTE.C ; ; ADD_PC_C - Adds a value in A to PC.C ; ADD_PC_C ADD PC.C STA PC.C BCC SKP_C INC PC.C+1 SKP_C JMP READBYTE.C ; ; PULSEON_C - Switches pulse width modulation on ! ; PULSEON_C LDA #0 STA FROM+1 STA RNDFLAG_C LDA (PC.C),Y ASL:ASL ADD (PC.C),Y ADC #PWM_START STA FROM LDA FROM+1 ADC ^PWM_START STA FROM+1 DEY LDA (FROM),Y STA RATEUP_C INY STY PULSEFLAG_C STY PULSEDIR_C LDA (FROM),Y STA CUP_C STA CUP2_C INY LDA (FROM),Y STA CDOWN_C STA CDOWN2_C INY LDA (FROM),Y STA PWL2_C INY LDA (FROM),Y STA PWH2_C LDA #2 JMP ADD_PC_C ; ;SHPWM_A SWITCHES ON RANDOM PULSE WIDTH,WITH SPEED DELAY ; SHPWM_A LDA (PC.A),Y STA RNDDELAY_A STA RNDDELAYR_A STY RNDFLAG_A DEY STY PULSEFLAG_A LDA #2 JMP ADD_PC_A ; ;SHPWM_B SWITCHES ON RANDOM PULSE WIDTH,WITH SPEED DELAY ; SHPWM_B LDA (PC.B),Y STA RNDDELAY_B STA RNDDELAYR_B STY RNDFLAG_B DEY STY PULSEFLAG_B LDA #2 JMP ADD_PC_B ; ;SHPWM_C SWITCHES ON RANDOM PULSE WIDTH,WITH SPEED DELAY ; SHPWM_C LDA (PC.C),Y STA RNDDELAY_C STA RNDDELAYR_C STY RNDFLAG_C DEY STY PULSEFLAG_C LDA #2 JMP ADD_PC_C ; ; Music control routines follow ...... ; ; ; JUMP.A - Jumps to a new sequence of notes ; JUMP.A LDA (PC.A),Y STA TEMP.PC ; Preserve the LOW byte new address INY LDA (PC.A),Y STA PC.A+1 ; New high byte into PC+1 LDA TEMP.PC STA PC.A ; Low byte in PC JMP READBYTE.A ; Back to sequencer ; ; CALL.A - Same as JSR, goes to a new sequence and returns on finding a RET ; CALL.A LDX SP.A ; Stack pointer, channel A LDA (PC.A),Y STA TEMP.PC ; TEMP.PC contains CALL address INY LDA (PC.A),Y STA TEMP.PC+1 LDA PC.A ADD #3 STA STACK.A.L,X ; Preserve current PC low byte LDA PC.A+1 ADC #0 STA STACK.A.H,X ; Preserve current PC high byte LDA TEMP.PC ; Set PC to CALL address STA PC.A LDA TEMP.PC+1 STA PC.A+1 INC SP.A ; Increment channel A stack pointer JMP READBYTE.A ; ; RET.A - Returns the last stacked PC value ; RET.A DEC SP.A ; Decrement channel A stack pointer LDX SP.A LDA STACK.A.L,X ; Retrieve Program counter low byte STA PC.A LDA STACK.A.H,X ; Retrieve Program counter high byte STA PC.A+1 LDA #0 STA TRANSVAL_A ; Reset the transpose value JMP READBYTE.A ; ; FOR.HANDLE.A - Handles the stacking of FOR instructions ; FOR.HANDLE.A LDX SP.A LDA (PC.A),Y STA FOR.COUNTS.A,X ; Store number of channel A FOR loops LDA PC.A ; Bump PC, and stack it's new value ADD #2 STA PC.A STA STACK.A.L,X BCC NOCARRY.A INC PC.A+1 NOCARRY.A LDA PC.A+1 STA STACK.A.H,X INC SP.A ; Bump channel A stack pointer JMP READBYTE.A ; ; NEXT.HANDLE.A - Handles unstacking PC and decrementing the FOR counters ; NEXT.HANDLE.A LDX SP.A ; SP.A only gets stored in LAST.NEXT DEX ; to preserve the FOR address DEC FOR.COUNTS.A,X BEQ LAST.NEXT.A LDA STACK.A.L,X ; Get back old for address STA PC.A LDA STACK.A.H,X STA PC.A+1 JMP READBYTE.A LAST.NEXT.A STX SP.A ; Decremented SP.A is now stored INC PC.A BNE NOCARRY2.A INC PC.A+1 NOCARRY2.A JMP READBYTE.A ; Back to sequencer ; ; JUMP.B - Jumps to a new sequence of notes ; JUMP.B ; Ditto LDA (PC.B),Y STA TEMP.PC INY LDA (PC.B),Y STA PC.B+1 LDA TEMP.PC STA PC.B JMP READBYTE.B ; ; CALL.B - Same as JSR, goes to a new sequence and returns on finding a RET ; CALL.B LDX SP.B ; Ditto LDA (PC.B),Y STA TEMP.PC INY LDA (PC.B),Y STA TEMP.PC+1 LDA PC.B ADD #3 STA STACK.B.L,X LDA PC.B+1 ADC #0 STA STACK.B.H,X LDA TEMP.PC STA PC.B LDA TEMP.PC+1 STA PC.B+1 INC SP.B JMP READBYTE.B ; ; RET.B - Returns the last stacked PC value ; RET.B DEC SP.B ; Ditto LDX SP.B LDA STACK.B.L,X STA PC.B LDA STACK.B.H,X STA PC.B+1 LDA #0 STA TRANSVAL_B JMP READBYTE.B ; ; FOR.HANDLE.B - Handles the stacking of FOR instructions ; FOR.HANDLE.B LDX SP.B ; Ditto LDA (PC.B),Y STA FOR.COUNTS.B,X LDA PC.B ADD #2 STA PC.B STA STACK.B.L,X BCC NOCARRY.B INC PC.B+1 NOCARRY.B LDA PC.B+1 STA STACK.B.H,X INC SP.B JMP READBYTE.B ; ; NEXT.HANDLE.B - Handles unstacking PC and decrementing the FOR counters ; NEXT.HANDLE.B LDX SP.B ; Ditto DEX DEC FOR.COUNTS.B,X BEQ LAST.NEXT.B LDA STACK.B.L,X STA PC.B LDA STACK.B.H,X STA PC.B+1 JMP READBYTE.B LAST.NEXT.B STX SP.B INC PC.B BNE NOCARRY2.B INC PC.B+1 NOCARRY2.B JMP READBYTE.B ; ; JUMP.C - Jumps to a new sequence of notes ; JUMP.C ; Ditto LDA (PC.C),Y STA TEMP.PC INY LDA (PC.C),Y STA PC.C+1 LDA TEMP.PC STA PC.C JMP READBYTE.C ; ; CALL.C - Same as JSR, goes to a new sequence and returns on finding a RET ; CALL.C LDX SP.C ; Ditto LDA (PC.C),Y STA TEMP.PC INY LDA (PC.C),Y STA TEMP.PC+1 LDA PC.C ADD #3 STA STACK.C.L,X LDA PC.C+1 ADC #0 STA STACK.C.H,X LDA TEMP.PC STA PC.C LDA TEMP.PC+1 STA PC.C+1 INC SP.C JMP READBYTE.C ; ; RET.C - Returns the last stacked PC value ; RET.C DEC SP.C ; Ditto LDX SP.C LDA STACK.C.L,X STA PC.C LDA STACK.C.H,X STA PC.C+1 LDA #0 STA TRANSVAL_C JMP READBYTE.C ; ; FOR.HANDLE.C - Handles the stacking of FOR instructions ; FOR.HANDLE.C LDX SP.C ; Ditto LDA (PC.C),Y STA FOR.COUNTS.C,X LDA PC.C ADD #2 STA PC.C STA STACK.C.L,X BCC NOCARRY.C INC PC.C+1 NOCARRY.C LDA PC.C+1 STA STACK.C.H,X INC SP.C JMP READBYTE.C ; ; NEXT.HANDLE.C - Handles unstacking PC and decrementing the FOR counters ; NEXT.HANDLE.C LDX SP.C ; Ditto DEX DEC FOR.COUNTS.C,X BEQ LAST.NEXT.C LDA STACK.C.L,X STA PC.C LDA STACK.C.H,X STA PC.C+1 JMP READBYTE.C LAST.NEXT.C STX SP.C INC PC.C BNE NOCARRY2.C INC PC.C+1 NOCARRY2.C JMP READBYTE.C ; ; VIBON_A - Acctivates the vibrato ; VIBON_A LDA (PC.A),Y STA VIBDELAY2_A ; Permenant vib delay INY LDA (PC.A),Y STA VIBRATE_A ; additive/subtractive rate INY LDA (PC.A),Y STA VIBDEPTH_A ; Variable vib depth LSR STA VIBDEPTH2_A ; Permenant vib depth LDX #1 STX VIBFLAG_A ; Signal vibrato is on DEX STX VIB_DIR_A ; Set the initial vibrato direction STX ARPFLAG_A ; Cancel arpeggio (if it is running) LDA #4 ; Bump the PC JMP ADD_PC_A ; ; VIBOFF_A - Guess moron ! ; VIBOFF_A LDA #0 ; Shut down the vibrato STA VIBFLAG_A INC PC.A ; Bump PC BNE SKIP2_A INC PC.A+1 SKIP2_A JMP READBYTE.A ; Back to the sequencer ; ; VIBON_B - Acctivates the vibrato ; VIBON_B ; Ditto LDA (PC.B),Y STA VIBDELAY2_B ; Permenant vib delay INY LDA (PC.B),Y STA VIBRATE_B INY LDA (PC.B),Y STA VIBDEPTH_B LSR STA VIBDEPTH2_B ; " " " " " depth LDX #1 STX VIBFLAG_B DEX STX VIB_DIR_B STX ARPFLAG_B LDA #4 JMP ADD_PC_B ; ; VIBOFF_B - Guess moron ! ; VIBOFF_B LDA #0 ; Ditto STA VIBFLAG_B INC PC.B BNE SKIP2_B INC PC.B+1 SKIP2_B JMP READBYTE.B ; ; VIBON_C - Acctivates the vibrato ; VIBON_C ; Ditto LDA (PC.C),Y STA VIBDELAY2_C ; Permenant vib delay INY LDA (PC.C),Y STA VIBRATE_C INY LDA (PC.C),Y STA VIBDEPTH_C LSR STA VIBDEPTH2_C ; " " " " " depth LDX #1 STX VIBFLAG_C DEX STX VIB_DIR_C STX ARPFLAG_C LDA #4 JMP ADD_PC_C ; ; VIBOFF_C - Guess moron ! ; VIBOFF_C LDA #0 ; Ditto STA VIBFLAG_C INC PC.C BNE SKIP2_C INC PC.C+1 SKIP2_C JMP READBYTE.C ; ; ARPON_A - Acctivates the arpeggiator ; ARPON_A LDA (PC.A),Y STA READ_A ; Get the address of the arpeggio INY LDA (PC.A),Y ; table STA READ_A+1 LDY #0 ; STY VIBFLAG_A LDA (READ_A),Y STA NEXTDELAY2_A ; Get the delay between reading bytes INY STY ARPFLAG_A ; Trigger the arpeggiator STY NEXTDELAY_A LDA (READ_A),Y ADD #2 STA ARPEGLEN_A ; Set the length of the arpeggio table INY STY ARPEGIND_A ; Set the index into the table LDA #3 ; Bump the PC JMP ADD_PC_A ; ; ARPOFF_A - No prizes dickhead ! ; ARPOFF_A LDA #0 ; Shut down the arpeggiator STA ARPFLAG_A INC PC.A ; Bump the PC BNE SKIP4_A INC PC.A+1 SKIP4_A JMP READBYTE.A ; Back to the sequencer ; ; ARPON_B - Acctivates the arpeggiator ; ARPON_B ; Ditto LDA (PC.B),Y STA READ_B INY LDA (PC.B),Y STA READ_B+1 LDY #0 ; STY VIBFLAG_B LDA (READ_B),Y STA NEXTDELAY2_B INY STY ARPFLAG_B STY NEXTDELAY_B LDA (READ_B),Y ADD #2 STA ARPEGLEN_B INY STY ARPEGIND_B LDA #3 JMP ADD_PC_B ; ; ARPOFF_B - No prizes dickhead ! ; ARPOFF_B LDA #0 ; Ditto STA ARPFLAG_B INC PC.B BNE SKIP4_B INC PC.B+1 SKIP4_B JMP READBYTE.B ; ; ARPON_C - Acctivates the arpeggiator ; ARPON_C ; Ditto LDA (PC.C),Y STA READ_C INY LDA (PC.C),Y STA READ_C+1 LDY #0 ; STY VIBFLAG_C LDA (READ_C),Y STA NEXTDELAY2_C INY STY ARPFLAG_C STY NEXTDELAY_C LDA (READ_C),Y ADD #2 STA ARPEGLEN_C INY STY ARPEGIND_C LDA #3 JMP ADD_PC_C ; ; ARPOFF_C - No prizes dickhead ! ; ARPOFF_C LDA #0 ; Ditto STA ARPFLAG_C INC PC.C BNE SKIP4_C INC PC.C+1 SKIP4_C JMP READBYTE.C ; ; MODE_A - Sets triggering mode, i'll be buggered if i know what this does ! ; MODE_A LDA (PC.A),Y BMI SETEM_A EOR #$FF AND MODEBYTE_A STA MODEBYTE_A LDA #2 JMP ADD_PC_A SETEM_A ORA MODEBYTE_A STA MODEBYTE_A LDA #2 JMP ADD_PC_A ; ; MODE_B - Sets triggering mode ; MODE_B LDA (PC.B),Y BMI SETEM_B EOR #$FF AND MODEBYTE_B STA MODEBYTE_B LDA #2 JMP ADD_PC_B SETEM_B ORA MODEBYTE_B STA MODEBYTE_B LDA #2 JMP ADD_PC_B ; ; MODE_C - Sets triggering mode ; MODE_C LDA (PC.C),Y BMI SETEM_C EOR #$FF AND MODEBYTE_C STA MODEBYTE_C LDA #2 JMP ADD_PC_C SETEM_C ORA MODEBYTE_C STA MODEBYTE_C LDA #2 JMP ADD_PC_C ; ; PORT_A - Sends 1 byte of data to an offset of the SID chip ; PORT_A LDA (PC.A),Y STA TEMP_VAL ; Store byte to be send to SID INY LDA (PC.A),Y ; Get sid offset TAX LDA TEMP_VAL ; Send value to SID STA $D400,X LDA #3 ; Bump the PC JMP ADD_PC_A PORT_B ; Ditto LDA (PC.B),Y STA TEMP_VAL INY LDA (PC.B),Y TAX LDA TEMP_VAL STA $D400,X LDA #3 JMP ADD_PC_B PORT_C ; Ditto LDA (PC.C),Y STA TEMP_VAL INY LDA (PC.C),Y TAX LDA TEMP_VAL STA $D400,X LDA #3 JMP ADD_PC_C ; ; CODE_A - Jumps to a machine code segment ; CODE_A LDA (PC.A),Y STA JUMP_MOD_A+1 ; Get the address of the code INY LDA (PC.A),Y ; to be JSR'd to STA JUMP_MOD_A+2 JUMP_MOD_A JSR $AAAA ; Self modified LDA #3 ; Bump the PC JMP ADD_PC_A CODE_B ; Ditto LDA (PC.B),Y STA JUMP_MOD_B+1 INY LDA (PC.B),Y STA JUMP_MOD_B+2 JUMP_MOD_B JSR $AAAA ; Self modified LDA #3 JMP ADD_PC_B CODE_C ; Ditto LDA (PC.C),Y STA JUMP_MOD_C+1 INY LDA (PC.C),Y STA JUMP_MOD_C+2 JUMP_MOD_C JSR $AAAA ; Self modified LDA #3 JMP ADD_PC_C ; ; EFFECT_A - Sets up effect mode ; EFFECT_A LDA (PC.A),Y STA EFFECT_NOTE_A STY EFFECTFLAG_A LDA #2 JMP ADD_PC_A EFFECT_B LDA (PC.B),Y STA EFFECT_NOTE_B STY EFFECTFLAG_B LDA #2 JMP ADD_PC_B EFFECT_C LDA (PC.C),Y STA EFFECT_NOTE_C STY EFFECTFLAG_C LDA #2 JMP ADD_PC_C ; ; GLISS_A - Acctivates and sets up glissando mode (!) ; GLISS_A LDA #$81 ; Minus to stop gliss reset first time STA GLISSFLAG_A LDA (PC.A),Y STA GLISSDIR_A ; Get glissando direction INY LDA (PC.A),Y STA GLISSCOUNT_A ; Get the count in before starting INY LDA (PC.A),Y STA GLISSRATE_A ; And the additive/subtractive LDA #4 JMP ADD_PC_A ; ; GLISS_B - Acctivates and sets up glissando mode (!) ; GLISS_B LDA #$81 STA GLISSFLAG_B LDA (PC.B),Y STA GLISSDIR_B INY LDA (PC.B),Y STA GLISSCOUNT_B INY LDA (PC.B),Y STA GLISSRATE_B LDA #4 JMP ADD_PC_B ; ; GLISS_C - Acctivates and sets up glissando mode (!) ; GLISS_C LDA #$81 STA GLISSFLAG_C LDA (PC.C),Y STA GLISSDIR_C INY LDA (PC.C),Y STA GLISSCOUNT_C INY LDA (PC.C),Y STA GLISSRATE_C LDA #4 JMP ADD_PC_C ; ; BEND.ON.A - Acctivates the Pitchbender & sets up the pitchbend data ; BEND.ON.A LDA #$81 ; Bend on+minus = initialise bend STA PORTFLAG.A LDA (PC.A),Y STA BEND.DIR.A ; Get the bend direction INY LDA (PC.A),Y STA BENDSTEP.A ; Get the steps INY LDA (PC.A),Y STA BENDLENGTH.A ; and the length INY LDA (PC.A),Y ; Bend offset (Rate x Duration) STA OFFSET.A INY LDA (PC.A),Y STA OFFSET.A+1 LDA #6 ; Bump the PC JMP ADD_PC_A ; ; BEND.ON.B - Acctivates the Pitchbender & sets up the pitchbend data ; BEND.ON.B LDA #$81 ; Bend on. Minus = init benda STA PORTFLAG.B LDA (PC.B),Y STA BEND.DIR.B ; Pitchbend direction INY LDA (PC.B),Y STA BENDSTEP.B ; Bend steps INY LDA (PC.B),Y STA BENDLENGTH.B INY LDA (PC.B),Y ; Bend offset (Rate x Duration) STA OFFSET.B INY LDA (PC.B),Y STA OFFSET.B+1 LDA #6 JMP ADD_PC_B ; ; BEND.ON.C - Acctivates the Pitchbender & sets up the pitchbend data ; BEND.ON.C LDA #$81 ; Bend on. Minus = init benda STA PORTFLAG.C LDA (PC.C),Y STA BEND.DIR.C ; Pitchbend direction INY LDA (PC.C),Y STA BENDSTEP.C ; Bend steps INY LDA (PC.C),Y STA BENDLENGTH.C INY LDA (PC.C),Y ; Bend offset (Rate x Duration) STA OFFSET.C INY LDA (PC.C),Y STA OFFSET.C+1 LDA #6 JMP ADD_PC_C ; ; PATCH.A - Pokes sound patch into SID chip Channel A ; PATCH.A LDA #0 STA FROM+1 ; Zeroise FROM+1 LDA (PC.A),Y ; Get patch number ASL ASL ADD (PC.A),Y ; *5 ADC #PATCH_START STA FROM LDA FROM+1 ; Plus patch base address ADC ^PATCH_START STA FROM+1 LDY #4 LDA (FROM),Y STA GATEOFF.A ; Get the gateoff value DEY LDX #0 LDA (FROM),Y ; Minus = gap mode BPL NO_GAP_A INX NO_GAP_A AND #$7F ; Get rid of bit 7 STA SUSTAIN_A STX GAPFLAG_A ; Set the gap flag (nonzero) DEY LDA (FROM),Y ; Get SR period STA $D406 STA SUSTEMP+0 ; Preserve this DEY LDA (FROM),Y STA $D405 ; Get the AD period STA ADTEMP+0 ; Preserve this DEY LDA (FROM),Y STA GATE.A ; Get the gateon value LDA #2 ; Bump the PC JMP ADD_PC_A ; ; PATCH.B - Pokes sound patch into SID chip Channel B ; PATCH.B LDA #0 ; Ditto STA FROM+1 LDA (PC.B),Y ASL ASL ADD (PC.B),Y ADC #PATCH_START STA FROM LDA FROM+1 ADC ^PATCH_START STA FROM+1 LDY #4 LDA (FROM),Y STA GATEOFF.B DEY LDX #0 LDA (FROM),Y BPL NO_GAP_B INX NO_GAP_B AND #$7F STA SUSTAIN_B STX GAPFLAG_B DEY LDA (FROM),Y STA $D406+7 STA SUSTEMP+1 DEY LDA (FROM),Y STA $D405+7 STA ADTEMP+1 DEY LDA (FROM),Y STA GATE.B LDA #2 JMP ADD_PC_B ; ; PATCH.C - Pokes sound patch into SID chip Channel C ; PATCH.C LDA #0 STA FROM+1 LDA (PC.C),Y ASL ASL ADD (PC.C),Y ADC #PATCH_START STA FROM LDA FROM+1 ADC ^PATCH_START STA FROM+1 LDY #4 LDA (FROM),Y STA GATEOFF.C DEY LDX #0 LDA (FROM),Y BPL NO_GAP_C INX NO_GAP_C AND #$7F STA SUSTAIN_C STX GAPFLAG_C DEY LDA (FROM),Y STA $D406+14 STA SUSTEMP+2 DEY LDA (FROM),Y STA $D405+14 STA ADTEMP+2 DEY LDA (FROM),Y STA GATE.C LDA #2 JMP ADD_PC_C ; ; DRUM_C - Gets new drum table pointers (DunnyDrums tm) ; DRUM_C LDA (PC.C),Y STA DRUMadd ASL ADD DRUMadd ASL ADC DRUMadd TAX LDA DRUMTABLE,X ;GET LO & HI BYTE OF WVFORM TABLE STA WAVES_L+2 ; LDA DRUMTABLE+1,X ; STA WAVES_H+2 ; LDA DRUMTABLE+2,X ;" "" " "" " FREQUENCY TABLE STA FREQS_L+2 ; LDA DRUMTABLE+3,X ; STA FREQS_H+2 ; LDA DRUMTABLE+4,X ;GET LENGTH OF DRUM TABLE STA DRUMlength+2 ; LDA DRUMTABLE+5,X ;GET VOLUME (SUTAIAN/RELEASE) STA drumFLAG+2 ; STA $D406+14 ; LDA DRUMTABLE+6,X ;GET PULSE WIDTH STA $D403+14 LDA #$00 ;ATTACK/DECAY STA $D405+14 ;FOR DRUMSOUND INY LDA (PC.C),Y STA DRUMtr+2 LDA DURATIONON_C BNE GRAB_DUR_C LDA DURATION_C STA DURCOUNT.C LDA #3 ADD_N_FALL_C ADD PC.C STA PC.C BCC NOLOW_C INC PC.C+1 NOLOW_C RTS GRAB_DUR_C INY LDA (PC.C),Y STA DURCOUNT.C LDA #4 JMP ADD_N_FALL_C ; ; DRUM_B - Gets new drum table pointers (DunnyDrums tm) ; DRUM_B LDA (PC.B),Y STA DRUMadd ASL ADD DRUMadd ASL ADC DRUMadd TAX LDA DRUMTABLE,X ;GET LO & HI BYTE OF WVFORM TABLE STA WAVES_L+1 ; LDA DRUMTABLE+1,X ; STA WAVES_H+1 ; LDA DRUMTABLE+2,X ;" "" " "" " FREQUENCY TABLE STA FREQS_L+1 ; LDA DRUMTABLE+3,X ; STA FREQS_H+1 ; LDA DRUMTABLE+4,X ;GET LENGTH OF DRUM TABLE STA DRUMlength+1 ; LDA DRUMTABLE+5,X ;GET VOLUME (SUTAIAN/RELEASE) STA drumFLAG+1 ; STA $D406+7 ; LDA DRUMTABLE+6,X ;GET PULSE WIDTH STA $D403+7 LDA #$00 ;ATTACK/DECAY STA $D405+7 ;FOR DRUMSOUND INY LDA (PC.B),Y STA DRUMtr+1 LDA DURATIONON_B BNE GRAB_DUR_B LDA DURATION_B STA DURCOUNT.B LDA #3 ADD_N_FALL_B ADD PC.B STA PC.B BCC NOLOW_B INC PC.B+1 NOLOW_B RTS GRAB_DUR_B INY LDA (PC.B),Y STA DURCOUNT.B LDA #4 JMP ADD_N_FALL_B ;----------DRUM PROGRAM-------------------- DRUMMER LDX #2 NEXT_DRUM LDA drumFLAG,X BEQ QUITDRUM LDA DRUMx,X CMP DRUMlength,X BNE DRUMcont LDA #0 STA $D417 STA DRUMx,X STA drumFLAG,X LDY SID_OFFSETS,X STA $D404,Y LDA SUSTEMP,X STA $D406,Y LDA ADTEMP,X STA $D405,Y QUITDRUM DEX BPL NEXT_DRUM RTS DRUMcont STX TEMPX_2 ; TEMPX+0 = Drum Number STA TEMPX_2+1 ; TEMPX+1 = Drum's position in table LDA FREQS_L,X STA DRUMFQ+1 LDA FREQS_H,X STA DRUMFQ+2 LDA WAVES_L,X STA DRUMWV+1 LDA WAVES_H,X STA DRUMWV+2 LDY SID_OFFSETS,X LDX TEMPX_2+1 ;GET CURRENT VOICE DRUMFQ LDA $DDDD,X ; LOAD FREQUENCY FROM TABLE (S/M/C) LDX TEMPX_2 ADD DRUMtr,X ; ADD TRANSPOSE BYTE LDX TEMPX_2+1 STA $D401,Y ; STORE IN SID FRQ HI DRUMWV LDA $DDDD,X ; LOAD WAVEFORM FROM TABLE (S/M/C) STA $D404,Y ; STORE IN SID WAVEFORM LDX TEMPX_2 INC DRUMx,X DEX BMI DRUMS_DONE JMP NEXT_DRUM DRUMS_DONE RTS ; ; END_A - Terminates the tune on that voice ; END_A LDA #0 STA MFL_A STA PORTFLAG.A STA VIBFLAG_A STA ARPFLAG_A STA PULSEFLAG_A STA RNDFLAG_A RTS END_B LDA #0 STA MFL_B STA PORTFLAG.B STA VIBFLAG_B STA ARPFLAG_B STA PULSEFLAG_B STA RNDFLAG_B RTS END_C LDA #0 STA MFL_C STA PORTFLAG.C STA VIBFLAG_C STA ARPFLAG_C STA PULSEFLAG_C STA RNDFLAG_C RTS DRUM_A NOTHING RTS ; FINITO ; ; Control tables... ; JUMPVECL.A DFL JUMP.A,CALL.A,RET.A,FOR.HANDLE.A,NEXT.HANDLE.A DFL BEND.ON.A,PATCH.A,LENGTH_A,VIBON_A,VIBOFF_A DFL ARPON_A,ARPOFF_A,DUR_ON_A,PULSEON_A,NOTHING DFL END_A,TRANS_A,CT_A,NOTHING,MODE_A,DRUM_A DFL PORT_A,CODE_A,EFFECT_A,GLISS_A,SHPWM_A JUMPVECH.A DFH JUMP.A,CALL.A,RET.A,FOR.HANDLE.A,NEXT.HANDLE.A DFH BEND.ON.A,PATCH.A,LENGTH_A,VIBON_A,VIBOFF_A DFH ARPON_A,ARPOFF_A,DUR_ON_A,PULSEON_A,NOTHING DFH END_A,TRANS_A,CT_A,NOTHING,MODE_A,DRUM_A DFH PORT_A,CODE_A,EFFECT_A,GLISS_A,SHPWM_A JUMPVECL.B DFL JUMP.B,CALL.B,RET.B,FOR.HANDLE.B,NEXT.HANDLE.B DFL BEND.ON.B,PATCH.B,LENGTH_B,VIBON_B,VIBOFF_B DFL ARPON_B,ARPOFF_B,DUR_ON_B,PULSEON_B,NOTHING DFL END_B,TRANS_B,CT_B,NOTHING,MODE_B,DRUM_B DFL PORT_B,CODE_B,EFFECT_B,GLISS_B,SHPWM_B JUMPVECH.B DFH JUMP.B,CALL.B,RET.B,FOR.HANDLE.B,NEXT.HANDLE.B DFH BEND.ON.B,PATCH.B,LENGTH_B,VIBON_B,VIBOFF_B DFH ARPON_B,ARPOFF_B,DUR_ON_B,PULSEON_B,NOTHING DFH END_B,TRANS_B,CT_B,NOTHING,MODE_B,DRUM_B DFH PORT_B,CODE_B,EFFECT_B,GLISS_B,SHPWM_B JUMPVECL.C DFL JUMP.C,CALL.C,RET.C,FOR.HANDLE.C,NEXT.HANDLE.C DFL BEND.ON.C,PATCH.C,LENGTH_C,VIBON_C,VIBOFF_C DFL ARPON_C,ARPOFF_C,DUR_ON_C,PULSEON_C,NOTHING DFL END_C,TRANS_C,CT_C,NOTHING,MODE_C,DRUM_C DFL PORT_C,CODE_C,EFFECT_C,GLISS_C,SHPWM_C JUMPVECH.C DFH JUMP.C,CALL.C,RET.C,FOR.HANDLE.C,NEXT.HANDLE.C DFH BEND.ON.C,PATCH.C,LENGTH_C,VIBON_C,VIBOFF_C DFH ARPON_C,ARPOFF_C,DUR_ON_C,PULSEON_C,NOTHING DFH END_C,TRANS_C,CT_C,NOTHING,MODE_C,DRUM_C DFH PORT_C,CODE_C,EFFECT_C,GLISS_C,SHPWM_C STACKDEPTH EQU 5 STACK.A.L DFS STACKDEPTH,0 STACK.B.L DFS STACKDEPTH,0 STACK.C.L DFS STACKDEPTH,0 STACK.A.H DFS STACKDEPTH,0 STACK.B.H DFS STACKDEPTH,0 STACK.C.H DFS STACKDEPTH,0 FOR.COUNTS.A DFS STACKDEPTH,0 FOR.COUNTS.B DFS STACKDEPTH,0 FOR.COUNTS.C DFS STACKDEPTH,0 SID_OFFSETS DFB 0,7,14 WORD_OFFSET DFB 0,2,4 LOWFREQ DFL N00,N01,N02,N03,N04,N05,N06,N07,N08,N09 DFL N10,N11,N12,N13,N14,N15,N16,N17,N18,N19 DFL N20,N21,N22,N23,N24,N25,N26,N27,N28,N29 DFL N30,N31,N32,N33,N34,N35,N36,N37,N38,N39 DFL N40,N41,N42,N43,N44,N45,N46,N47,N48,N49 DFL N50,N51,N52,N53,N54,N55,N56,N57,N58,N59 DFL N60,N61,N62,N63,N64,N65,N66,N67,N68,N69 DFL N70,N71,N72,N73,N74,N75,N76,N77,N78,N79 DFL N80,N81,N82,N83,N84,N85,N86,N87,N88,N89 DFL N90,N91,N92,N93,000 HIFREQ DFH N00,N01,N02,N03,N04,N05,N06,N07,N08,N09 DFH N10,N11,N12,N13,N14,N15,N16,N17,N18,N19 DFH N20,N21,N22,N23,N24,N25,N26,N27,N28,N29 DFH N30,N31,N32,N33,N34,N35,N36,N37,N38,N39 DFH N40,N41,N42,N43,N44,N45,N46,N47,N48,N49 DFH N50,N51,N52,N53,N54,N55,N56,N57,N58,N59 DFH N60,N61,N62,N63,N64,N65,N66,N67,N68,N69 DFH N70,N71,N72,N73,N74,N75,N76,N77,N78,N79 DFH N80,N81,N82,N83,N84,N85,N86,N87,N88,N89 DFH N90,N91,N92,N93,000 DRIVER.END EQU . ;------------------------------------------------------------------------------ DATA.START EQU . TUNETABLE.A.L DFL START1,END1,TITLE1 TUNETABLE.A.H DFH START1,END1,TITLE1 TUNETABLE.B.L DFL START2,END2,TITLE2 TUNETABLE.B.H DFH START2,END2,TITLE2 TUNETABLE.C.L DFL START3,END3,TITLE3 TUNETABLE.C.H DFH START3,END3,TITLE3 ;-------------------4/4------------------------------------------------------- ;TEMPO EQU 6 ; TEMPO CONTROL ;DSQ EQU TEMPO/2 ; DEMI-SEMI-QUAVER ;SQ EQU TEMPO ; SEMI-QUAVER ;QV EQU SQ*2 ; QUAVER ;CR EQU QV*2 ; CROTCHET ;DCR EQU CR+QV ;MN EQU CR*2 ; MINIM ;SB EQU MN*2 ; SEMI-BREVE ;SB EQU MN*2 ; SEMI-BREVE ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- TEMPO EQU 6 ; TEMPO CONTROL DSQ EQU TEMPO/2 ; DEMI-SEMI-QUAVER SQ EQU TEMPO ; SEMI-QUAVER QV EQU SQ*2 ; QUAVER DQV EQU SQ+QV ; QUAVER CR EQU QV*2 ; CROTCHET DCR EQU CR+QV ; DOTTED CROTCHET MN EQU CR*2 ; MINIM SB EQU MN*2 ; SEMI-BREVE ;----------------------------------------------------------------------------- ;--GAME START MUSIC----N.B This tune is 3/4 time------------------------------ ;----------------------------------------------------------------------------- START1 DFL PATCH,0,PWM,0,VIBON,0,7,6 STARTLOOP1 DFL CALL:DFW BASS1 DFL CALL:DFW BASS1 DFL CALL:DFW BASS1 DFL CT,-5:DFW BASS1 DFL CALL:DFW BASS1 DFL CT,-5:DFW BASS1 DFL CT,-4:DFW BASS1 DFL CT,-2:DFW BASS1 DFL CT,-4:DFW BASS1 DFL CT,-5:DFW BASS1 DFL CALL:DFW BASS1 DFL CT,-4:DFW BASS1 DFL CALL:DFW BASS1 DFL CT,-4:DFW BASS1 DFL JUMP:DFW STARTLOOP1 ;----------------------------------------------------------------------------- START2 DFL LOOP,4*10 DFL DRUM,2,0,QV DFL DRUM,2,0,SQ DFL DRUM,3,0,QV DFL DRUM,2,0,SQ DFL NEXT DFL LOOP,4*4 DFL DRUM,2,0,QV DFL DRUM,2,0,SQ DFL DRUM,2,0,QV DFL DRUM,2,0,SQ DFL NEXT DFL JUMP:DFW START2 DFL END ;----------------------------------------------------------------------------- START3 DFL REST,72 DFL PATCH,1,PWM,1,VIBON,4,7,6 DFL G2,SQ,A2,SQ,B2,SQ,E2,54+72+72 DFL PATCH,2,SHPWM,2,VIBON,9,$20,6 DFL LOOP,2 DFL E4,30,B4,6,G4,30,D5,6 DFL B4,48,B4,18,B4,6 DFL B4,72*2 DFL NEXT DFL C4,30,B3,6,C4,30,B3,6 DFL C4,48,B3,18,B4,6 DFL D4,72*2 DFL C4,30,B3,6,C4,30,B3,6 DFL C4,48,B3,18,B4,6 DFL E4,72,D#4,72 DFL PATCH,3,PWM,3 DFL ARPON:DFW ARP1 DFL LOOP,2 DFL DRUM,3,5,CR+SQ DFL DRUM,3,3,CR DFL DRUM,3,1,18 DFL E2,QV,E3,SQ,F#2,QV,F#3,SQ,G2,QV,G3,SQ,B2,QV,B3,SQ DFL MANUAL DFL DRUM,3,5,CR+SQ DFL DRUM,3,3,CR DFL DRUM,3,1,18 DFL C2,QV,C3,SQ,D2,QV,D3,SQ,E2,QV,E3,SQ,G2,QV,G3,SQ DFL MANUAL DFL NEXT DFL JUMP:DFW START3 ARP1 DFL 1,2,24,0 ;----------------------------------------------------------------------------- ;-----END OF LEVEL JINGLE----------------------------------------------------- ;----------------------------------------------------------------------------- END1 DFL PATCH,4,PWM,4 DFL VIBON,20,$70,6 DFL A4,CR,B4,CR,C5,SQ,B4,SQ,A4,QV+MN DFL D4,SQ,C5,SQ,B4,QV+CR+QV DFL A4,QV,A4,QV,A4,QV+MN ; MN = DELAY BEFOR CUTOFF DFL END END2 DFL REST,MN DFL PATCH,6,PWM,6,VIBON,5,$90,6 DFL G4,SQ,A4,SQ,B4,SQ,C5,SQ+MN DFL A4,SQ,B4,SQ,C5,SQ,D5,SQ+MN DFL B4,SQ,C5,SQ,D5,SQ,E5,SQ+MN DFL CODE:DFW TURNOFF DFL END END3 DFL PATCH,5,PWM,5,VIBON,0,7,6 DFL A2,CR,B2,CR,A2,CR+MN+QV DFL B2,MN+QV DFL A2,CR+MN ; MN = DELAY BEFOR CUTOFF DFL END ;----------------------------------------------------------------------------- BASS1 DFL E2,QV+SQ,E2,QV+SQ,E2,QV+SQ,E2,SQ,E2,SQ,E2,SQ DFL E2,QV+SQ,E2,QV+SQ,E2,QV+SQ,E2,SQ,E2,SQ,E2,SQ DFL RET ;----------------------------------------------------------------------------- ;----TITLE MUSIC-------------------------------------------------------------- ;----------------------------------------------------------------------------- TITLE1 DFL PATCH,8,PWM,9 DFL EFFECT,F7,MODE,%00001000 DFL VIBON,2,$10,6 DFL LENGTH,QV DFL LOOP,8+8+8 DFL CALL:DFW TBACK1 DFL NEXT DFL LENGTH,SQ,PATCH,12,ARPON:DFW TARP5 DFL LOOP,2 DFL CT,3:DFW TBACK2 DFL CT,-2:DFW TBACK2 DFL CALL:DFW TBACK2 DFL CT,5:DFW TBACK2 DFL NEXT DFL CT,3:DFW TBACK2 DFL CT,3:DFW TBACK2 DFL LENGTH,QV,PATCH,8 DFL VIBON,2,$10,6 DFL LOOP,8+240 DFL CALL:DFW TBACK1 DFL NEXT DFL END ;----------------------------------------------------------------------------- TITLE2 DFL PATCH,7,PWM,7,VIBON,0,7,6 DFL LENGTH,SQ DFL CODE:DFW RESETVOL DFL LOOP,16 VOLVAR DFL PORT,0,$18 DFL CODE:DFW UPVOL DFL CALL:DFW TBASS2 DFL NEXT DFL LOOP,16 DFL CALL:DFW TBASS2 DFL NEXT DFL LOOP,4 DFL CALL:DFW TBASS2 DFL CALL:DFW TBASS2 DFL CT,5:DFW TBASS2 DFL CT,5:DFW TBASS2 DFL NEXT DFL LOOP,2 DFL CT,3:DFW TBASS2 DFL CT,3:DFW TBASS2 DFL CT,-2:DFW TBASS2 DFL CT,-2:DFW TBASS2 DFL CALL:DFW TBASS2 DFL CALL:DFW TBASS2 DFL CT,5:DFW TBASS2 DFL CT,5:DFW TBASS2 DFL NEXT DFL LOOP,4 DFL CT,3:DFW TBASS2 DFL NEXT DFL LOOP,4+240 DFL CALL:DFW TBASS2 DFL CALL:DFW TBASS2 DFL CT,5:DFW TBASS2 DFL CT,5:DFW TBASS2 DFL NEXT DFL END ;----------------------------------------------------------------------------- TITLE3 DFL LOOP,8,REST,SB*2,NEXT; ** WAIT FOR INTRO END DFL PATCH,9,PWM,8 DFL LOOP,2 DFL ARPON:DFW TARP1 DFL G4,SB*2 DFL ARPON:DFW TARP2 DFL G4,SB*2 DFL ARPON:DFW TARP3 DFL F4,SB*2 DFL ARPON:DFW TARP4 DFL F4,SB*2 DFL NEXT DFL PWM,10,VIBON,20,$60,6 DFL LOOP,2 DFL CALL:DFW TMEL1 DFL NEXT DFL PATCH,13,SHPWM,6 ; DFL ARPON:DFW TARP6 DFL LOOP,2 DFL D#3,SB*2 DFL REST,SB*2 DFL C3,SB*2 DFL REST,SB*2 DFL NEXT DFL REST,SB*2 DFL REST,SB*2 DFL PWM,10,VIBON,20,$60,6 DFL LOOP,2 DFL CALL:DFW TMEL1 DFL NEXT DFL PWM,11,VIBON,18,$D0,4 DFL PATCH,14 DFL LOOP,2 DFL G4,CR,G#4,QV,G4,MN DFL D4,SQ,F4,SQ,G4,CR,G#4,QV,G4,MN,D4,QV DFL C5,QV,G4,CR,D5,QV,G4,CR,D#5,QV,G4,CR DFL F5,QV,G4,CR,D#5,CR,D5,CR DFL NEXT DFL END TARP1 DFL 3,7,0,5,8,12,17,20,24 TARP2 DFL 3,7,0,3,7,12,15,19,24 TARP3 DFL 3,7,0,4,7,12,16,19,24 TARP4 DFL 3,7,0,5,9,12,17,21,24 TARP5 DFL 1,2,12,0 TARP6 DFL 2,2,0,12 ;----------------------------------------------------------------------------- TMEL1 DFL PATCH,10 DFL D#5,DCR,D5,DCR,C5,CR DFL G4,MN+DCR,A4,SQ,A#4,SQ DFL G#4,SB*2 DFL PATCH,11 DFL GLISS,UP,0,40 DFL C4,SB*2 DFL GLISS,DOWN,0,40 DFL C5,SB*2-CR DFL LOOP,4 DFL DRUM,0,2,SQ DFL NEXT DFL RET TBASS2 DFL C1,C2,C3,D3,DRUM,3,0 DFL C3,C1,C2,C3,D#3,C1,D3,DRUM,3,0 DFL REST,D3,C2,RET TBACK1 DFL C5,G4,C5,G4,C5,G4,C5,G4,D#5,G4,D#5,G4,D5,G4,D5,G4 DFL RET TBACK2 DFL C1,C2,C3,C4,C5,C6,C7,C6,C5,C4,C3,C4,C5,C4,C3,C2 DFL C1,C2,C3,C4,C5,C6,C7,C6,C5,C4,C3,C4,C5,C4,C3,C2 DFL RET RESETVOL LDA #0 STA VOLVAR+1 RTS UPVOL INC VOLVAR+1 RTS ;---PATCH TABLE--------------------------------------------------------------- PATCH_START DFL $55,$00,$B9,2,$40 ; 00 DFL $41,$00,$9E,2,$40 ; 01 DFL $41,$00,$48,3+GAP,$12; 02 DFL $81,$00,$89,2,$40 ; 03 DFL $41,$00,$8C,2,$40 ; 04 DFL $55,$00,$5C,3,$40 ; 05 DFL $41,$00,$29,3+GAP,$20; 06 DFL $51,$00,$79,3,$40 ; 07 DFL $81,$00,$49,3,$40 ; 08 DFL $43,$CC,$09,3+GAP,$12; 09 DFL $41,$00,$5B,3+GAP,$14; 10 DFL $13,$00,$48,3+GAP,$14; 11 DFL $81,$00,$79,2,$12 ; 12 DFL $43,$00,$6F,3+GAP,$12; 13 DFL $41,$00,$4A,2+GAP,$12; 14 ;---PWM TABLE----------------------------------------------------------------- PWM_START DFL $20,$00,$02:DFW $0100; 00 DFL $50,$18,$10:DFW $0000; 01 DFL $30,$07,$05:DFW $0000; 02 DFL $10,$06,$06:DFW $0400; 03 DFL $40,$08,$06:DFW $0000; 04 DFL $40,$00,$02:DFW $0FA0; 05 DFL $40,$05,$05:DFW $0800; 06 DFL $20,$10,$10:DFW $0080; 07 DFL $03,$02,$00:DFW $0000; 08 DFL $FF,$05,$05:DFW $0080; 09 DFL $20,$10,$0D:DFW $0080; 10 DFL $C0,$06,$05:DFW $0200; 11 ;-----DRUM TABLE & DATA--------------------- DRUMTABLE DFW DRUM1V,DRUM1F:DFL 4,$A6,$08; 0 DFW DRUM2V,DRUM2F:DFL 13,$A9,$08; 1 DFW DRUM3V,DRUM3F:DFL 7,$88,$00; 2 DFW DRUM4V,DRUM4F:DFL 15,$C9,$08; 3 DFW DRUM3V,DRUM3F:DFL 5,$F5,$02; 4 DFW DRUM5V,DRUM5F:DFL 10,$C9,$08; 5 ;-----BASS DRUM------ DRUM1V DFB $41,$41,$10,$80 DRUM1F DFB $0B,$0A,$15,$14 ;-----SNARE---------- DRUM2V DFB $41,$41,$40,$80,$10,$80,$10,$80,$10,$80,$80,$10,$80 DRUM2F DFB $0C,$0B,$0A,$B0,$10,$1F,$10,$1E,$0C,$1D,$1C,$0C,$2B ;-----HI-HAT--------- DRUM3V DFB $15,$15,$80,$80,$80,$80,$80,$80 DRUM3F DFB $0B,$0B,$80,$C0,$C8,$D0,$E0,$FF ;-----TOM-1---------- DRUM4V DFB $11,$11,$80,$10,$80,$10,$80,$10,$80,$10,$80,$10,$80,$10,$80 DRUM4F DFB $0D,$0C,$60,$0A,$A0,$0B,$9E,$0A,$9C,$09,$9A,$08,$98,$07,$96 ;-----SNARE 2-------- DRUM5V DFB $41,$41,$40,$80,$40,$40,$40,$80,$80,$80 DRUM5F DFB $14,$12,$0F,$60,$0E,$0A,$09,$40,$30,$20 TURNOFF LDA #8 STA $D404 STA $D404+7 STA $D404+14 LDA #0 STA $D404 STA $D404+7 STA $D404+14 RTS DATA.END EQU . ;------------------------------------------------------------------------------ UP EQU 1 DOWN EQU $80 GAP EQU $80 NO EQU 0 FILTIT EQU 1 REST EQU 94 ;REST JUMP EQU $80 ;JUMP:DFW LABEL CALL EQU $81 ;CALL:DFW LABEL RET EQU $82 ;RET LOOP EQU $83 ;LOOP,LOOP COUNTS NEXT EQU $84 ;NEXT BEND EQU $85 ;BEND,UP/DOWN,STEPS,CYCLES:STEPS*CYCLES PATCH EQU $86 ;PATCH,PATCH NUMBER LENGTH EQU $87 ;LENGTH,DURATION VIBON EQU $88 ;VIBON,DELAY,STEPS,CYCLES VIBOFF EQU $89 ;VIBOFF ARPON EQU $8A ;ARPON:DFW LABEL ARPOFF EQU $8B ;ARPOFF MANUAL EQU $8C ;MANUAL PWM EQU $8D ;PWM,PWM NUMBER FILTER EQU $8E ;N/A END EQU $8F ;END TRANSPOSE EQU $90 ;TRANSPOSE,VALUE CT EQU $91 ;CT,TRANSPOSE VALUE:LABEL FILTOFF EQU $92 ;N/A MODE EQU $93 ;MODE,%01111111 (SETS ALL BITS TO 0) DRUM EQU $94 ;DRUM,DRUM NUMBER,TRAN VALUE,DURATION PORT EQU $95 ;PORT,VALUE,SID REGISTER CODE EQU $96 ;CODE:DFW LABEL EFFECT EQU $97 ;EFFECT,EFFECT NOTE GLISS EQU $98 ;GLISS,DIRECTION,DELAY,STEPS SHPWM EQU $99 ;SHPWM,RATE VAR_START FILT_TOGGLE DFB 0 FILT_TOGFLAG DFB 0 DURCOUNT.A DFB 0 DURCOUNT.B DFB 0 DURCOUNT.C DFB 0 TEMP.PC DFB 0,0 ; 2 bytes GATE.A DFB 0 GATE.B DFB 0 GATE.C DFB 0 SP.A DFB 0 SP.B DFB 0 SP.C DFB 0 PORTFLAG.A DFB 0 PORTFLAG.B DFB 0 PORTFLAG.C DFB 0 BEND.DIR.A DFB 0 BEND.DIR.B DFB 0 BEND.DIR.C DFB 0 BENDSTEP.A DFB 0 BENDSTEP.B DFB 0 BENDSTEP.C DFB 0 FREQ.LOW.A DFB 0 FREQ.LOW.B DFB 0 FREQ.LOW.C DFB 0 FREQ.HI.A DFB 0 FREQ.HI.B DFB 0 FREQ.HI.C DFB 0 OFFSET.A DFB 0,0 ; 2 bytes OFFSET.B DFB 0,0 ; 2 bytes OFFSET.C DFB 0,0 ; 2 bytes BENDLENGTH.A DFB 0 BENDLENGTH.B DFB 0 BENDLENGTH.C DFB 0 RELEASE_A DFB 0 RELEASE_B DFB 0 RELEASE_C DFB 0 SUSTAIN_A DFB 0 SUSTAIN_B DFB 0 SUSTAIN_C DFB 0 DURATION_A DFB 0 DURATION_B DFB 0 DURATION_C DFB 0 VIBFLAG_A DFB 0 VIBFLAG_B DFB 0 VIBFLAG_C DFB 0 VIBDELAY_A DFB 0 VIBDELAY_B DFB 0 VIBDELAY_C DFB 0 VIBDELAY2_A DFB 0 VIBDELAY2_B DFB 0 VIBDELAY2_C DFB 0 VIBDEPTH_A DFB 0 VIBDEPTH_B DFB 0 VIBDEPTH_C DFB 0 VIBDEPTH2_A DFB 0 VIBDEPTH2_B DFB 0 VIBDEPTH2_C DFB 0 VIBRATE_A DFB 0 VIBRATE_B DFB 0 VIBRATE_C DFB 0 VIB_DIR_A DFB 0 VIB_DIR_B DFB 0 VIB_DIR_C DFB 0 NEXTDELAY_A DFB 0 NEXTDELAY_B DFB 0 NEXTDELAY_C DFB 0 NEXTDELAY2_A DFB 0 NEXTDELAY2_B DFB 0 NEXTDELAY2_C DFB 0 ARPEGLEN_A DFB 0 ARPEGLEN_B DFB 0 ARPEGLEN_C DFB 0 ARPEGIND_A DFB 0 ARPEGIND_B DFB 0 ARPEGIND_C DFB 0 ARPFLAG_A DFB 0 ARPFLAG_B DFB 0 ARPFLAG_C DFB 0 GATEOFF.A DFB 0 GATEOFF.B DFB 0 GATEOFF.C DFB 0 NOTE_A DFB 0 NOTE_B DFB 0 NOTE_C DFB 0 DURATIONON_A DFB 0 DURATIONON_B DFB 0 DURATIONON_C DFB 0 PULSEDIR_A DFB 0 PULSEDIR_B DFB 0 PULSEDIR_C DFB 0 RATEUP_A DFB 0 RATEUP_B DFB 0 RATEUP_C DFB 0 RATEDOWN_A DFB 0 RATEDOWN_B DFB 0 RATEDOWN_C DFB 0 CUP_A DFB 0 CUP_B DFB 0 CUP_C DFB 0 CUP2_A DFB 0 CUP2_B DFB 0 CUP2_C DFB 0 CDOWN_A DFB 0 CDOWN_B DFB 0 CDOWN_C DFB 0 CDOWN2_A DFB 0 CDOWN2_B DFB 0 CDOWN2_C DFB 0 PWL_A DFB 0 PWL_B DFB 0 PWL_C DFB 0 PWL2_A DFB 0 PWL2_B DFB 0 PWL2_C DFB 0 PWH_A DFB 0 PWH_B DFB 0 PWH_C DFB 0 PWH2_A DFB 0 PWH2_B DFB 0 PWH2_C DFB 0 PULSEFLAG_A DFB 0 PULSEFLAG_B DFB 0 PULSEFLAG_C DFB 0 GAPFLAG_A DFB 0 GAPFLAG_B DFB 0 GAPFLAG_C DFB 0 MFL_A DFB 0 MFL_B DFB 0 MFL_C DFB 0 TRANSVAL_A DFB 0 TRANSVAL_B DFB 0 TRANSVAL_C DFB 0 MODEBYTE_A DFB 0 MODEBYTE_B DFB 0 MODEBYTE_C DFB 0 VOICE_NUM DFB 0 DRUMadd DFB 0 DRUMx DFS 3,0 drumFLAG DFS 3,0 DRUMtr DFS 3,0 DRUMlength DFS 3,0 WAVES_L DFS 3,0 WAVES_H DFS 3,0 FREQS_L DFS 3,0 FREQS_H DFS 3,0 VOLUMES DFS 3,0 RELEASE.TEMP DFB 0 ATTACK.TEMP DFB 0 TEMP_VAL DFB 0 EFFECTFLAG_A DFB 0 EFFECTFLAG_B DFB 0 EFFECTFLAG_C DFB 0 EFFECT_NOTE_A DFB 0 EFFECT_NOTE_B DFB 0 EFFECT_NOTE_C DFB 0 REAL_NOTE_A DFB 0 REAL_NOTE_B DFB 0 REAL_NOTE_C DFB 0 GLISSFLAG_A DFB 0 GLISSFLAG_B DFB 0 GLISSFLAG_C DFB 0 GLISSDIR_A DFB 0 GLISSDIR_B DFB 0 GLISSDIR_C DFB 0 GLISSCOUNT_A DFB 0 GLISSCOUNT_B DFB 0 GLISSCOUNT_C DFB 0 GLISSRATE_A DFB 0 GLISSRATE_B DFB 0 GLISSRATE_C DFB 0 TEMPX_2 DFB 0,0 ; 2 Bytes SUSTEMP DFS 3,0 ADTEMP DFS 3,0 RNDFLAG_A DFB 0 RNDFLAG_B DFB 0 RNDFLAG_C DFB 0 RNDDELAY_A DFB 0 RNDDELAY_B DFB 0 RNDDELAY_C DFB 0 RNDDELAYR_A DFB 0 ;RESET VALUES RNDDELAYR_B DFB 0 ; RNDDELAYR_C DFB 0 ; VAR_END EQU . PROG.END EQU . ;------------------------------------------------------------------------------ SID EQU $D400 ; PAL Note frequency table N00 EQU 279 N01 EQU 296 N02 EQU 314 N03 EQU 332 N04 EQU 352 N05 EQU 373 N06 EQU 395 N07 EQU 419 N08 EQU 444 N09 EQU 470 N10 EQU 498 N11 EQU 528 N12 EQU 559 N13 EQU 592 N14 EQU 627 N15 EQU 665 N16 EQU 704 N17 EQU 746 N18 EQU 790 N19 EQU 837 N20 EQU 887 N21 EQU 940 N22 EQU 996 N23 EQU 1055 N24 EQU 1118 N25 EQU 1184 N26 EQU 1255 N27 EQU 1330 N28 EQU 1408 N29 EQU 1492 N30 EQU 1581 N31 EQU 1675 N32 EQU 1774 N33 EQU 1880 N34 EQU 1992 N35 EQU 2110 N36 EQU 2236 N37 EQU 2369 N38 EQU 2509 N39 EQU 2659 N40 EQU 2817 N41 EQU 2984 N42 EQU 3162 N43 EQU 3350 N44 EQU 3549 N45 EQU 3760 N46 EQU 3984 N47 EQU 4220 N48 EQU 4471 N49 EQU 4737 N50 EQU 5019 N51 EQU 5317 N52 EQU 5634 N53 EQU 5969 N54 EQU 6324 N55 EQU 6700 N56 EQU 7098 N57 EQU 7520 N58 EQU 7967 N59 EQU 8441 N60 EQU 8943 N61 EQU 9475 N62 EQU 10038 N63 EQU 10635 N64 EQU 11267 N65 EQU 11937 N66 EQU 12647 N67 EQU 13399 N68 EQU 14195 N69 EQU 15040 N70 EQU 15934 N71 EQU 16881 N72 EQU 17886 N73 EQU 18949 N74 EQU 20076 N75 EQU 21270 N76 EQU 22534 N77 EQU 23875 N78 EQU 25294 N79 EQU 26798 N80 EQU 28391 N81 EQU 30080 N82 EQU 31869 N83 EQU 33764 N84 EQU 35771 N85 EQU 37898 N86 EQU 40151 N87 EQU 42540 N88 EQU 45069 N89 EQU 47749 N90 EQU 50588 N91 EQU 53596 N92 EQU 56783 N93 EQU 60160 C0 EQU 0 C#0 EQU 1 D0 EQU 2 D#0 EQU 3 E0 EQU 4 F0 EQU 5 F#0 EQU 6 G0 EQU 7 G#0 EQU 8 A0 EQU 9 A#0 EQU 10 B0 EQU 11 C1 EQU 12 C#1 EQU 13 D1 EQU 14 D#1 EQU 15 E1 EQU 16 F1 EQU 17 F#1 EQU 18 G1 EQU 19 G#1 EQU 20 A1 EQU 21 A#1 EQU 22 B1 EQU 23 C2 EQU 24 C#2 EQU 25 D2 EQU 26 D#2 EQU 27 E2 EQU 28 F2 EQU 29 F#2 EQU 30 G2 EQU 31 G#2 EQU 32 A2 EQU 33 A#2 EQU 34 B2 EQU 35 C3 EQU 36 C#3 EQU 37 D3 EQU 38 D#3 EQU 39 E3 EQU 40 F3 EQU 41 F#3 EQU 42 G3 EQU 43 G#3 EQU 44 A3 EQU 45 A#3 EQU 46 B3 EQU 47 C4 EQU 48 C#4 EQU 49 D4 EQU 50 D#4 EQU 51 E4 EQU 52 F4 EQU 53 F#4 EQU 54 G4 EQU 55 G#4 EQU 56 A4 EQU 57 A#4 EQU 58 B4 EQU 59 C5 EQU 60 C#5 EQU 61 D5 EQU 62 D#5 EQU 63 E5 EQU 64 F5 EQU 65 F#5 EQU 66 G5 EQU 67 G#5 EQU 68 A5 EQU 69 A#5 EQU 70 B5 EQU 71 C6 EQU 72 C#6 EQU 73 D6 EQU 74 D#6 EQU 75 E6 EQU 76 F6 EQU 77 F#6 EQU 78 G6 EQU 79 G#6 EQU 80 A6 EQU 81 A#6 EQU 82 B6 EQU 83 C7 EQU 84 C#7 EQU 85 D7 EQU 86 D#7 EQU 87 E7 EQU 88 F7 EQU 89 F#7 EQU 90 G7 EQU 91 G#7 EQU 92 A7 EQU 93 A#7 EQU 94 B7 EQU 95 BUFFER DFS 65,0 PAGE.>$BFFF," Overwriting Graphics, where's me memory gone ? " ; ; The End (!) ;