void CChannelHandler::UpdateEffects() { // Handle other effects switch (m_iEffect) { case EF_ARPEGGIO: if (m_iArpeggio != 0) { switch (m_iArpState) { case 0: m_iPeriod = TriggerNote(m_iNote); break; case 1: m_iPeriod = TriggerNote(m_iNote + (m_iArpeggio >> 4)); if ((m_iArpeggio & 0x0F) == 0) ++m_iArpState; break; case 2: m_iPeriod = TriggerNote(m_iNote + (m_iArpeggio & 0x0F)); break; } m_iArpState = (m_iArpState + 1) % 3; } break; case EF_PORTAMENTO: case EF_SLIDE_UP: case EF_SLIDE_DOWN: // Automatic portamento if (m_iPortaSpeed > 0 && m_iPortaTo > 0) { if (m_iPeriod > m_iPortaTo) { PeriodRemove(m_iPortaSpeed); // TODO: check this // if (m_iPeriod > 0x1000) // it was negative // m_iPeriod = 0x00; if (m_iPeriod < m_iPortaTo) m_iPeriod = m_iPortaTo; } else if (m_iPeriod < m_iPortaTo) { PeriodAdd(m_iPortaSpeed); if (m_iPeriod > m_iPortaTo) m_iPeriod = m_iPortaTo; } } break; case EF_PORTA_DOWN: PeriodAdd(m_iPortaSpeed); m_iPeriod = LimitPeriod(m_iPeriod); break; case EF_PORTA_UP: PeriodRemove(m_iPortaSpeed); m_iPeriod = LimitPeriod(m_iPeriod); break; } }
unsigned char processControls(void){ static int lastbuttons=0; unsigned int joy=ReadJoypad(0); if((joy&BTN_START) && !(lastbuttons&BTN_START)){ } if(joy&BTN_X){ TriggerNote(3,1,23,0xff); while(ReadJoypad(0)!=0); } if(joy&BTN_Y){ tracks[3].flags&= ~(TRACK_FLAGS_PLAYING); tracks[3].noteVol=0; } if(joy&BTN_SELECT){ while(ReadJoypad(0)!=0); } lastbuttons=joy; return 0; }
//Callback invoked by UzeboxCore.Initialize() void DisplayLogo(){ #if INTRO_LOGO !=0 #define LOGO_X_POS 18 InitMusicPlayer(logoInitPatches); SetTileTable(uzeboxlogo); //draw logo ClearVram(); WaitVsync(15); #if INTRO_LOGO == 1 TriggerFx(0,0xff,true); #endif DrawMap2(LOGO_X_POS,12,map_uzeboxlogo); WaitVsync(6); DrawMap2(LOGO_X_POS,12,map_uzeboxlogo2); WaitVsync(4); DrawMap2(LOGO_X_POS,12,map_uzeboxlogo); #if INTRO_LOGO == 2 SetMasterVolume(0xc0); TriggerNote(3,0,16,0xff); #endif WaitVsync(64); ClearVram(); WaitVsync(20); #endif }
//Callback invoked by UzeboxCore.Initialize() void DisplayLogo(){ #if INTRO_LOGO !=0 #define LOGO_X_POS 8 InitMusicPlayer(logoInitPatches); screenSections[0].tileTableAdress=uzeboxlogo; //draw logo ClearVram(); WaitVsync(15); #if INTRO_LOGO == 1 TriggerFx(0,0xff,true); #endif DrawMap(LOGO_X_POS,12,map_uzeboxlogo); WaitVsync(3); DrawMap(LOGO_X_POS,12,map_uzeboxlogo2); WaitVsync(2); DrawMap(LOGO_X_POS,12,map_uzeboxlogo); #if INTRO_LOGO == 2 SetMasterVolume(0xc0); TriggerNote(3,0,16,0xff); #endif WaitVsync(65); ClearVram(); WaitVsync(20); #endif }
void CChannelHandler::SetupSlide(int Type, int EffParam) { #define GET_SLIDE_SPEED(x) (((x & 0xF0) >> 3) + 1) m_iPortaSpeed = GET_SLIDE_SPEED(EffParam); m_iEffect = Type; if (Type == EF_SLIDE_UP) m_iNote = m_iNote + (EffParam & 0xF); else m_iNote = m_iNote - (EffParam & 0xF); m_iPortaTo = TriggerNote(m_iNote); }
/** * Main code */ int main() { SetTileTable(tiles); SetSpritesTileTable(tiles); SetFontTilesIndex(TILE_FIRST_FONT); InitMusicPlayer(patches); TriggerNote(3,SOUND_INTRO_MUSIC,20,0xff); SetUserPostVsyncCallback(vsync_callback); // read custom configuration from eeprom EepromReadBlock(129, &eeprom_data); eeprom_data.id = 129; game(); }
int CChannelHandler::RunNote(int Octave, int Note) { // Run the note and handle portamento int NewNote = MIDI_NOTE(Octave, Note); int NesFreq = TriggerNote(NewNote); if (m_iPortaSpeed > 0 && m_iEffect == EF_PORTAMENTO) { if (m_iPeriod == 0) m_iPeriod = NesFreq; m_iPortaTo = NesFreq; } else m_iPeriod = NesFreq; m_bGate = true; return NewNote; }
void CChannelHandler::Arpeggiate(unsigned int Note) { m_iPeriod = TriggerNote(Note); }
int main(){ unsigned char i,c,x,y,spr; ClearVram(); //initialize stuff InitMusicPlayer(patches); SetMasterVolume(0xc0); //crank up the volume a bit since the sample is not too loud SetSpritesTileTable(cubes_tileset); SetSpritesOptions(SPR_OVERFLOW_CLIP); //To allocate/deallocate a player's voice //tracks[0].allocated=false; //tracks[1].allocated=false; //tracks[2].allocated=false; //start the beat loop TriggerNote(3,1,23,0xff); //Define the screen sections. for(i=0;i<9;i++){ screenSections[i].tileTableAdress=spritedemo_tileset; } screenSections[0].height=76; screenSections[0].flags=SCT_PRIORITY_SPR; screenSections[1].height=2; screenSections[1].vramBaseAdress=vram+(32*37); screenSections[1].flags=SCT_PRIORITY_BG; screenSections[2].height=3; screenSections[2].vramBaseAdress=vram+(32*37); screenSections[2].flags=SCT_PRIORITY_BG; screenSections[2].scrollY=2; screenSections[3].height=3; screenSections[3].vramBaseAdress=vram+(32*37); screenSections[3].flags=SCT_PRIORITY_BG; screenSections[3].scrollY=5; screenSections[4].height=40; screenSections[4].vramBaseAdress=vram+(32*32); screenSections[4].flags=SCT_PRIORITY_SPR; screenSections[5].height=3; screenSections[5].vramBaseAdress=vram+(32*38); screenSections[5].flags=SCT_PRIORITY_BG; screenSections[6].height=3; screenSections[6].vramBaseAdress=vram+(32*38); screenSections[6].flags=SCT_PRIORITY_BG; screenSections[6].scrollY=3; screenSections[7].height=2; screenSections[7].vramBaseAdress=vram+(32*38); screenSections[7].flags=SCT_PRIORITY_BG; screenSections[7].scrollY=6; screenSections[8].height=76; screenSections[8].flags=SCT_PRIORITY_SPR; screenSections[8].scrollY=132; Fill(0,37,32,1,1); Fill(0,38,32,1,2); for(y=0;y<30;y+=4){ for(x=0;x<30;x+=5){ DrawMap2(x,y,map_bg); } } DrawMap2(0,32,map_logo); for(i=22;i<32;i++){ DrawMap2(i,32,map_bar); } srand(18); c=1; spr=1; for(i=0;i<7;i++){ //randomize positions cubes[i].x=((unsigned char)(rand() % 110))+2; cubes[i].y=((unsigned char)(rand() % 180))+2; cubes[i].rotation=((unsigned char)(rand() % 7)); if((unsigned char)(rand() % 16)<10){ cubes[i].xdir=1; }else{ cubes[i].xdir=-1; } if((unsigned char)(rand() % 16)<8){ cubes[i].ydir=1; }else{ cubes[i].ydir=-1; } } c=0; char w1=0,w2=0; while(1){ //syncronize gameplay on vsync (30 hz) WaitVsync(1); w2++; if(w2==3){ sx3++; if(sx3>X_SCROLL_WRAP) sx3=0; screenSections[1].scrollX=sx3; screenSections[7].scrollX=sx3; w2=0; } w1++; if(w1==2){ sx2++; if(sx2>=X_SCROLL_WRAP) sx2=0; screenSections[2].scrollX=sx2; screenSections[6].scrollX=sx2; w1=0; } sx++; if(sx>=X_SCROLL_WRAP) sx=0; screenSections[3].scrollX=sx; screenSections[4].scrollX=sx; screenSections[5].scrollX=sx; screenSections[0].scrollY++; screenSections[8].scrollY++; spr=1; for(i=0;i<7;i++){ cubes[i].x+=cubes[i].xdir; cubes[i].y+=cubes[i].ydir; if(cubes[i].x>123 && cubes[i].xdir==1){ cubes[i].xdir=-1; } if(cubes[i].x<9 && cubes[i].xdir==-1){ cubes[i].xdir=1; } cubes[i].y+=cubes[i].ydir; if(cubes[i].y>=196 && cubes[i].ydir==1){ cubes[i].ydir=-1; } if(cubes[i].y<10 && cubes[i].ydir==-1){ cubes[i].ydir=1; } if(c==0){ cubes[i].rotation++; if(cubes[i].rotation==14)cubes[i].rotation=0; sprites[spr+0].tileIndex=(cubes[i].rotation*2)+1; sprites[spr+1].tileIndex=(cubes[i].rotation*2)+1+1; sprites[spr+2].tileIndex=(cubes[i].rotation*2)+1+29; sprites[spr+3].tileIndex=(cubes[i].rotation*2)+1+30; } sprites[spr+0].x=cubes[i].x; sprites[spr+0].y=cubes[i].y; sprites[spr+1].x=cubes[i].x+6; sprites[spr+1].y=cubes[i].y; sprites[spr+2].x=cubes[i].x; sprites[spr+2].y=cubes[i].y+8; sprites[spr+3].x=cubes[i].x+6; sprites[spr+3].y=cubes[i].y+8; spr+=4; c+=128; } processControls(); } }
void ProcessMusic(void){ u8 c1,c2,tmp,trackVol; s16 vol; u16 uVol,tVol; u8 channel; struct TrackStruct* track; //process patches envelopes & pitch slides for(unsigned char trackNo=0;trackNo<CHANNELS;trackNo++){ track=&tracks[trackNo]; //update envelope if(track->envelopeStep!=0){ vol=track->envelopeVol+track->envelopeStep; if(vol<0){ vol=0; }else if(vol>0xff){ vol=0xff; } track->envelopeVol=vol; } if(track->flags & TRACK_FLAGS_SLIDING){ mixer.channels.all[trackNo].step+=track->slideStep; u16 tStep=pgm_read_word(&(steptable[track->slideNote])); if((track->slideStep>0 && mixer.channels.all[trackNo].step>=tStep) || (track->slideStep<0 && mixer.channels.all[trackNo].step<=tStep)) { mixer.channels.all[trackNo].step = tStep; track->flags &= ~(TRACK_FLAGS_SLIDING); } } } //Process song MIDI notes if(playSong){ #if MUSIC_ENGINE == MIDI //process all simultaneous events while(currDeltaTime==nextDeltaTime){ c1=pgm_read_byte(songPos++); if(c1==0xff){ //META data type event c1=pgm_read_byte(songPos++); if(c1==0x2f){ //end of song playSong=false; break; }else if(c1==0x6){ //marker c1=pgm_read_byte(songPos++); //read len c2=pgm_read_byte(songPos++); //read data if(c2=='S'){ //loop start loopStart=songPos; }else if(c2=='E'){//loop end songPos=loopStart; } } }else{ if(c1&0x80) lastStatus=c1; channel=lastStatus&0x0f; //get next data byte //Note: maybe we should not advance the cursor //in case we receive an unsupported command if(c1&0x80) c1=pgm_read_byte(songPos++); switch(lastStatus&0xf0){ //note-on case 0x90: //c1 = note c2=pgm_read_byte(songPos++)<<1; //get volume if(tracks[channel].flags|TRACK_FLAGS_ALLOCATED){ //allocated==true TriggerNote(channel,tracks[channel].patchNo,c1,c2); } break; //controllers case 0xb0: ///c1 = controller # c2=pgm_read_byte(songPos++); //get controller value if(c1==CONTROLER_VOL){ tracks[channel].trackVol=c2<<1; }else if(c1==CONTROLER_EXPRESSION){ tracks[channel].expressionVol=c2<<1; }else if(c1==CONTROLER_TREMOLO){ tracks[channel].tremoloLevel=c2<<1; }else if(c1==CONTROLER_TREMOLO_RATE){ tracks[channel].tremoloRate=c2<<1; } break; //program change case 0xc0: // c1 = patch # tracks[channel].patchNo=c1; break; }//end switch(c1&0xf0) }//end if(c1==0xff) //read next delta time nextDeltaTime=ReadVarLen(&songPos); currDeltaTime=0; #if SONG_SPEED == 1 if(songSpeed != 0){ uint32_t l = (uint32_t)(nextDeltaTime<<8); if(songSpeed < 0){//slower (uint32_t)(l += (uint32_t)(-songSpeed*(nextDeltaTime<<1))); (uint32_t)(l >>= 8); } else//faster (uint32_t)(l /= (uint32_t)((1<<8)+(songSpeed<<1))); nextDeltaTime = l; }