/*****************************************************************************************
*
*
* Copyright 2008 by Jowan Sebastian
* No Rights Reserved.
*
*
* Version Date Author Log
* --------------------------------------------------------------------------------------
* 0.2 01.05.08 Jowan Sebastian new features - yay
*
****************************************************************************************/
/*
*general includes
**/
#include <gb/gb.h>
/*
* graphics and hardware config
**/
#include "bangmap01.c"
#include "bangtiles01.c"
#include "pioport.h"
/*
* decalring sprites
**/
#define NOTEOFF 0
#define NOTEON 1
#define NOTEOFFOVER 2
#define MUTEON 3
#define MUTEOFF 4
#define SPEEUP 5
#define SPEEDWN 6
#define RIGHTEND 7
#define RIGHTMARK 8
#define LEFTMARK 9
#define LEFTEND 10
#define EMPTY 11
#define POINTER 12
#define NOTEONOVER 13
#define MUTEONOVER 14
#define MUTEOFFOVER 15
#define LBEG 16
#define LEND 17
/*
* global variables
**/
unsigned char tiles[] ={NOTEOFF,NOTEON,NOTEOFFOVER,MUTEON,MUTEOFF,SPEEUP,SPEEDWN,RIGHTEND,RIGHTMARK,LEFTMARK,LEFTEND,EMPTY,POINTER,NOTEONOVER,MUTEONOVER,LBEG,LEND};
UBYTE matrix[8][32]; // drum grid
UBYTE channel[8]; // state of channels of play position
UBYTE ch_mute[8]; // channel mutes on or off
UBYTE addr; // value to be passed to
/*
* move sprites function
**/
void move(int s_x,int s_y, UINT8 s_tile) {
bangmap01[s_x+s_y*20]=s_tile;
set_bkg_tiles(s_x,s_y,1,1,tiles+s_tile);
}
void counter(int c_x,int c_y, UINT8 c_tile) {
set_bkg_tiles(c_x,c_y,1,1,tiles+c_tile);
}
/*
* make hardware address x value y function
**/
void gb_out(UBYTE B) {
GBWR_REG = B;
}
/*
* main loop
*
**/
void main(){
// LOCAL VARIABLES
UBYTE ch_1,ch_2,ch_3,ch_4,ch_5,ch_6,ch_7,ch_8,key;
int x,y,c,d;
int p;
unsigned int len;
unsigned int lcnt;
unsigned int speed;
unsigned int scrl;
SHOW_BKG; // needed for gameboy original
set_bkg_data(0,70,bangtiles); // imports the sprites
set_bkg_tiles(0,0,32,18,bangmap01); // sets the tiles
gb_out(0x00); // set all pins low
x=0;y=1; // set coordinates to 0,1 top left of screen
c=0;d=0;
ch_1=0x00;ch_2=0x00; // give channel variables hex value of 0
ch_3=0x00;ch_4=0x00; // "
ch_5=0x00;ch_6=0x00; // "
ch_7=0x00;ch_8=0x00; // "
lcnt=0; // play position in loop
speed=100; // initial delay in milisecs -> speed
len=15; // initial length of loop value
scrl=1; // initial scroll value
move(x,y,NOTEOFFOVER); // NOTEOFFOVER is labeled wrong, it is actually the position pointer,
move(len,10,LBEG); // places loop end sprite
for( c=0; c<9; c++ ) { // empty matrix
for( d=0; d<31; d++ ) {
matrix[c][d]=0;
}
}
for( c=0; c<9; c++ ) { // set all mute values to off - 1
ch_mute[c]=0;
}
// infinate loop for main app
while(1){
gb_out(0x00); // turn all pins low
delay(speed); // delay by speed value
key = joypad(); // copy joypad value to key
if(lcnt>=len){ // increment play position counter to the right,
move(lcnt,9,EMPTY); // until reaches loop end, then back to start
lcnt=-1;
}
lcnt++;
move(lcnt,9,POINTER); // places counter sprite
move(lcnt-1,9,EMPTY); // hides trailing sprite with blank
// checks to see if there is a value in the matrix at position x by y and if the mute is off
// if neither true, adds a hex value representing the physcal pin on hardware
// this is much easier with binary but C has no support for that fot some reason
if(matrix[1][lcnt]==1 && ch_mute[1]==0){ move(1,0,MUTEON); ch_1=0x01;}else{ch_1=0x00;}
if(matrix[2][lcnt]==1 && ch_mute[2]==0){ move(5,0,MUTEON); ch_2=0x02;}else{ch_2=0x00;}
if(matrix[3][lcnt]==1 && ch_mute[3]==0){ move(9,0,MUTEON); ch_3=0x04;}else{ch_3=0x00;}
if(matrix[4][lcnt]==1 && ch_mute[4]==0){ move(13,0,MUTEON); ch_4=0x08;}else{ch_4=0x00;}
if(matrix[5][lcnt]==1 && ch_mute[5]==0){ move(17,0,MUTEON); ch_5=0x10;}else{ch_5=0x00;}
if(matrix[6][lcnt]==1 && ch_mute[6]==0){ move(21,0,MUTEON); ch_6=0x20;}else{ch_6=0x00;}
if(matrix[7][lcnt]==1 && ch_mute[7]==0){ move(25,0,MUTEON); ch_7=0x40;}else{ch_7=0x00;}
if(matrix[8][lcnt]==1 && ch_mute[8]==0){ move(29,0,MUTEON); ch_8=0x80;}else{ch_8=0x00;}
// add channel values together in hex
addr = ch_1 + ch_2 + ch_3 + ch_4 + ch_5 + ch_6 + ch_7 + ch_8;
// set pins high / low according to value
gb_out(addr);
// min system delay for master loops
delay(50);
p=1;
// turns all channel indicator led sprites off on top of screen
while(p<30){
move(p,0,MUTEOFF);
p+=4;
}
p=y*4-2;
// combination moves picked up slightly differnently
if(key & J_UP) {
if (key & J_START ){ // start and up -> speeds up
if(speed>=10){ // 10 min
speed=speed-5; // decrease speed / delay value
};
}
}
if(key & J_DOWN) {
if (key & J_START ){ // start and up -> speeds down
if(speed<=200){ // 200 max
speed=speed+10; // increases speed / delay value
};
}
}
if(key & J_UP) { // select and up -> mutes channel cursor is on
if (key & J_SELECT ){ // SPEEUP wrongly labled -> muteon
move(p,0,SPEEUP); // place muteon sprite in place
ch_mute[y]=1; // give channel mute value 1
}
}
if(key & J_DOWN) { // select and down -> unmutes channel cursor is on
if (key & J_SELECT ){ // SPEEDWN wrongly labled -> muteoff
move(p,0,SPEEDWN); // place muteoff sprite in place
ch_mute[y]=0; // give channel mute value 0
}
}
if(key & J_RIGHT) { // start and right -> increase loop length
if (key & J_START ){
if (len < 31){ // max is 31 -> 2 bar 32 steps
len++; // increment
move(len,10,LBEG); // move sprite
move(len-1,10,EMPTY); // hide trail
}
}
}
if(key & J_LEFT) { // start and left -> decrease loop length
if (key & J_START ){
if (len > 2){ // min is 2
len--; // decrement
move(len,10,LBEG); // move sprite
move(len+1,10,EMPTY); // hide trail
}
}
}
if(key & J_RIGHT) { // select and right -> scroll screen to right
if (key & J_SELECT ){
if(scrl<7){ // only 7 steps
scroll_bkg(+16,0); // each step is 16 pixels, move by 16 in x axis
scrl++; // increment
}
}
}
if(key & J_LEFT) { // select and right -> scroll screen to right
if (key & J_SELECT ){
if(scrl>2){
scroll_bkg(-16,0);
scrl--; // decrement
}
}
}
// single button moves picked up by switch method
switch (joypad(0))
{
case (J_RIGHT): // move cursor right
if(x<=31){
if(matrix[y][x]==1){
move(x,y,NOTEON);
x=x+1;
}else{
move(x,y,NOTEOFF);
x=x+1;
}
if(matrix[y][x]==1){
move(x,y,NOTEONOVER);
}else{
move(x,y,NOTEOFFOVER);
}
}
break; // end right
case (J_LEFT): // move cursor left
if(x>=1){
if(matrix[y][x]==1){
move(x,y,NOTEON);
x=x-1;
}else{
move(x,y,NOTEOFF);
x=x-1;
}
if(matrix[y][x]==1){
move(x,y,NOTEONOVER);
}else{
move(x,y,NOTEOFFOVER);
}
}
break; // end left
case (J_UP): // move cursor up
if(y>=2){
if(matrix[y][x]==1){
move(x,y,NOTEON);
y=y-1;
}else{
move(x,y,NOTEOFF);
y=y-1;
}
if(matrix[y][x]==1){
move(x,y,NOTEONOVER);
}else{
move(x,y,NOTEOFFOVER);
}
}
break; // end up
case (J_DOWN): // move cursor down
if(y<=8){
if(matrix[y][x]==1){
move(x,y,NOTEON);
y=y+1;
move(x,y,NOTEONOVER);
}else{
move(x,y,NOTEOFF);
y=y+1;
move(x,y,NOTEOFFOVER);
}
if(matrix[y][x]==1){
move(x,y,NOTEONOVER);
}else{
move(x,y,NOTEOFFOVER);
}
};
break; // end down
case (J_A): // note off at x y
move(x,y,NOTEOFFOVER); // place noteoff sprite
matrix[y][x]=0; // give matrix x y value of 0
break; // end start
case (J_B): // note on at x y
move(x,y,NOTEON); // place noteon sprite
matrix[y][x]=1; // give matrix x y value of 1
break; // end select
} // end button switch
} // end constant loop
} // end void