/* * SIDDEMO.C, ÖERSION 2 * * ÆOR THE Ã-64 AND Ã-ÐOWER. * * BY: ÓTEVE ÒEISMAN * 50 ÄAVID ÃOURT * ÄAYTON, ÎÊ 08810 * ATTMAIL!SREISMAN * * ÐROGRAM IS BASED ON: * "ÍÕÓÉÃ2" * ÁÈÏÙ ÍAGAZINE, ÊUNE 1986 * * ÕNLIKE VERSION 1, THIS DEMO CONSISTANTLY * PLAYS FULL, CRISP NOTES. * * ÐROGRAM DEMONSTRATES SEVERAL DISCRETE * CONCEPTS WHILE HARNESSING A POWERFUL * FEATURE OF THE Ã-64; SOUND GENERATION. * * 1. ÆROM Ã, THE Ã64'S NORMAL INTERRUPT PROCESSING * IS DYNAMICALLY ALTERED TO PERFORM AN INDEPENDENT * MACHINE LANGUAGE BASED ROUTINE. ÉN THIS CASE, * A TIGHT 6502 ROUTINE TIMES EACH NOTE'S PLAY * WITHOUT REGARD TO ANYTHING ELSE GOING ON. * * 2. ÔHE KEYBOARD IS ACCESSED DIRECTLY AND WITHOUT * ANY COSTLY OVERHEAD. ÇRANTED THAT THE KEY'S SCAN * CODE ONLY IS RETURNED, BUT THE METHOD HAS MANY * PRACTICAL APPLICATIONS FOR OTHER SOFTWARE. * * 3. ÔHE EMPLOYED ÍÌ ROUTINES, UNLIKE THE EARLIER VERSION * OF THIS PROGRAM, ARE STATIONARY. ÔHEY ARE NO LONGER * POKED ELSEWHERE IN ÒÁÍ. ÔHEIR ADDRESSES ARE CULLED * FOR SYS() CALLS USING POINTERS AND INDIRECTION. * * 4. ÌASTLY, THE PROGRAM EMPLOYS THE GOOD SENSE OF * CLEANING-UP AFTER ITSELF (THOUGH ONE LAST BUG * LINGERS ON HERE; YOU'LL SEE IT WHEN YOU END * PRACTICING YOUR TUNES). * * ÙOUR COMMENTS WILL BE APPRECIATED. ÄROP ME A LINE AT * MY ADDRESS (LISTED ABOVE), OR THROUGH THE ÐÒÏ-ÌÉÎÅ BBS. * * ÈAVE FUN! */ #INCLUDE #DEFINE PEEK(X) *((CHAR *)X) #DEFINE POKE(X,Y) *((CHAR *)X)=Y #DEFINE ÓÆÄØ 0Xà/* ËEYBOARD SCAN CODE TAKEN */ /* FROM HERE. */ #DEFINE ÔÉÍÅÒ 0XÆ /* ZERO-PAGE VARIABLE/FIELD */ #DEFINE ÕÓÒÁÄ1 0X311 #DEFINE ÕÓÒÁÄ2 0X312 #DEFINE ÃÉÎÖ1 0X314 #DEFINE ÃÉÎÖ2 0X315 #DEFINE ÓÉÄ 0XÄ400 #DEFINE ÆÒÅÌÏ1 0XÄ400 #DEFINE ÆÒÅÈÉ1 0XÄ401 #DEFINE Ð×ÌÏ1 0XÄ402 #DEFINE Ð×ÈÉ1 0XÄ403 #DEFINE ÖÃÒÅÇ1 0XÄ404 #DEFINE ÁÔÄÃÙ1 0XÄ405 #DEFINE ÓÕÒÅÌ1 0XÄ406 #DEFINE ÓÉÇÖÏÌ 0XÄ418 /* ËEYBOARD SCAN CODES FOR PROGRAM'S VALID KEYS. */ STATIC CHAR MATRIX[] = Û62,10, 9,13,18,17,21,22,26,29,30, 34,33,37,38,42,45,46,50,49,53 Ý; /* ÆREQUENCY TABLES FOR PIANO NOTES USED HEREIN * Æ/Ù/É - THE SID CHIP USED A 12-BIT VALUE FOR * A DESIRED FREQUENCY. ÔHE HIFREQ VALUES * ARE PLACED INTO THE REQUIRED NYBBLE, * AND THE LOFREQ'S ARE PLACED AS WHOLE * BYTES. */ STATIC CHAR HIFREQ[] = Û13,14,14,15,16,17,18,19,21,22,23,25, 26,28,29,31,33,35,37,39,42 Ý; STATIC CHAR LOFREQ[] = Û 78,24,239,210,195,195,209,239,31,96,181, 30,156,49,223,165,135,134,162,223,62 Ý; /* ÔHIS ÍÌ IS USED TO TIME NOTE DURATION. */ STATIC CHAR ML[] = Û 0XÁ6,0XÆÂ, /* ×ÁÉÔ LDX ÔÉÍÅÒ */ 0XÃÁ, /* DEX */ 0XÄ0,0X07, /* BNE ÒÔÒÎ */ 0XÁ9,0X40, /* LDA #64 */ 0X8Ä,0X04,0XÄ4, /* STA ÖÃÒÅÇ1 */ 0XÁ2,0X00, /* LDX #0 */ 0X86,0XÆÂ, /* ÒÔÒÎ STX ÔÉÍÅÒ */ 0X6Ã,0X11,0X03, /* ÊÍÐ JMP (ÕÓÒÁÄ1/2) */ 0X00 /* BRK */ Ý; /* ÆOLLOWING ARE TWO EXTREMELY SHORT ML ROUTINES * CALLED WITH SYS() TO DISABLE AND THEN RE-ENABLE * THE 64'S INTERRUPT MACHINE. * ÔHE POINTER FIELDS ARE USED TO SYS() TO THE ML. */ STATIC CHAR SEI[] =Û 0X78,0X60 Ý; STATIC CHAR CLI[] =Û 0X58,0X60 Ý; CHAR *SEIRTN, *CLIRTN, *MLRTN; MAIN() Û REGISTER INT I; STATIC CHAR C; STATIC CHAR CC; CHAR DMY; UNSIGNED INT ML¤ADR, ML¤LO, ML¤HI; /* ÓET UP INTERRUPT VECTOR. * * ÆIRST, GET CURRENT ÉÒÑ VECTOR BYTE * AND INSERT INTO ÕÓÅÒ VECTOR. */ C = PEEK(ÃÉÎÖ1); POKE(ÕÓÒÁÄ1, C); C = PEEK(ÃÉÎÖ2); POKE(ÕÓÒÁÄ2, C); /* ÒETRIEVE AND CONVERT ADDRESS * FOR ARITHMETIC OPERATIONS. * ÒESULTS ARE USED FOR SETTING * A NEW ÃÉÎÖ VECTOR. */ SEIRTN = &SEI[0]; CLIRTN = &CLI[0]; MLRTN = &ML[0]; ML¤ADR = MLRTN; ML¤HI = ML¤ADR / 256; ML¤LO = ML¤ADR - (ML¤HI * 256); /* ÒESET ÃÉÎÖ FOR NEW VECTOR. */ SYS(SEIRTN, &DMY, &DMY, &DMY); POKE(ÃÉÎÖ1, ML¤LO); POKE(ÃÉÎÖ2, ML¤HI); SYS(CLIRTN, &DMY, &DMY, &DMY); /* ÉNITIALIZE AND LOAD SID FOR DEMO. */ POKE(ÔÉÍÅÒ, 60); CLSID(); POKE( ÓÉÇÖÏÌ, 15 ); POKE( ÁÔÄÃÙ1, 9 ); POKE( ÓÕÒÅÌ1, 0 ); POKE( Ð×ÈÉ1, 0 ); POKE( Ð×ÌÏ1, 255 ); POKE( ÖÃÒÅÇ1, 64 ); MAPOUT(); /* DISPLAY INSTRUCTIONS */ CC = 0X00; /* INITIALIZE ÌAST-ËEY-ÈIT */ /* ÍAINLINE ROUTINE; PLAY THE KEYS. * ÅSCAPE BY PRESSING 'X'; */ ÌÏÏÐ: C = PEEK(ÓÆÄØ); /* GET SCAN CODE */ IF(C == 0X40)Û /* 0X40 = 'ÎO ËEY ÐRESSED */ CC = 0X00; /* UPDATE ÌAST-ËEY-ÈIT */ GOTO ÌÏÏÐ; Ý IF(C == 0X17)Û /* 0X17 IS SCAN CODE FOR 'X' */ MOPUP(); EXIT(0); Ý IF(C == CC) /* KEY MUST BE LIFTED .. */ GOTO ÌÏÏÐ; /* .. TO PLAY IT AGAIN */ FOR(I=0; I<21; I++)Û /* SEARCH FOR A VALID KEY */ IF(C == MATRIX[I])Û /* GOT ONE; PLAY IT */ CC = C; /* UPDATE ÌAST-ËEY-ÈIT */ POKE(ÔÉÍÅÒ, 60); POKE(ÖÃÒÅÇ1, 64); /* TURN ÖOICE-1 OFF */ POKE(ÆÒÅÈÉ1, HIFREQ[I]); /* ÓET FREQUENCY */ POKE(ÆÒÅÌÏ1, LOFREQ[I]); POKE(ÖÃÒÅÇ1, 65); /* TURN ÖOICE-1 ON */ GOTO ÌÏÏÐ; Ý Ý GOTO ÌÏÏÐ; Ý CLSID() Û REGISTER INT I; FOR(I = 0; I < 24; I++) POKE(ÓÉÄ + I, 0); Ý MAPOUT() Û PUTCHAR(147); PUTCHAR('\N'); PUTCHAR('\N'); PUTS(" ÓÉÄÄÅÍÏ.à -- Á DEMO PIANO PLAYER"); PUTCHAR('\N'); PUTCHAR('\N'); PUTCHAR('\N'); PUTS(" ÕSE INDICATED KEYS."); PUTCHAR('\N'); PUTCHAR('\N'); PUTS("ÂÌÁÃË ËÅÙÓ Ñ× ÒÔ ÕÉÏ @*"); PUTS(" NOTES -> GA CD FGA CD"); PUTS(" ## ## ### ##"); PUTCHAR('\N'); PUTS("×ÈÉÔÅ ËÅÙÓ ÁÓÄÆÇÈÊËÌ:;="); PUTS(" NOTES -> ABCDEFGABCDE"); PUTCHAR('\N'); PUTCHAR('\N'); PUTS(" ÂEGIN NOW. ÅNJOY!"); PUTCHAR('\N'); PUTS(" ÐRESS TO EXIT."); Ý MOPUP() Û CHAR C, DMY; SYS(SEIRTN, &DMY, &DMY, &DMY); /* DISABLE INTERUPTS */ C = PEEK(ÕÓÒÁÄ1); /* RESTORES */ POKE(ÃÉÎÖ1, C); /* TO */ C = PEEK(ÕÓÒÁÄ2); /* ORIGINAL */ POKE(ÃÉÎÖ2, C); /* VECTORS */ SYS(CLIRTN, &DMY, &DMY, &DMY); /* ENABLE INTERRUPTS */ CLSID(); /* ZAP ÓÉÄ'S REGISTERS */ Ý /* END */