Code:
import "std.zh"

bool isSolid(int x, int y) {

	// x=23, y=130
	// Obviously in range...
	if(x<0 || x>255 || y<0 || y>175)
					return false;
	int mask=1111b;
		
	// x &#37; 16 = 7, so
	// mask = 1111 & 0011 = 0011
	if(x%16<8)
		mask&=0011b;
	else
		mask&=1100b;
	
	// y % 16 = 2, so
	// mask = 0011 & 0101 = 0001
	if(y%16<8)
		mask&=0101b;
	else
		mask&=1010b;

	// All but the top-right quarter of the combo is solid, so ComboS = 1011
	// mask & ComboS = 0001 & 1011 = 0001
	// The result wasn't 0, so return false
	return (!(Screen->ComboS[ComboAt(x, y)]&mask)==0);

}



global script roll {

	void run() {

		int counter;
		bool justRolled = false;
		int DustTile = 20; //the starting animation tile of the 5-frame dust animation.
		int DustCSet = 7; //the CSet of the tile animation.
		int xca; int xcb; int xcc; int xcd; int xce;
		int yca; int ycb; int ycc; int ycd; int yce;
		int DustFrame;

		while(true) {

			if(Link->InputL && Link->Action == LA_WALKING) {

				Link->Jump = 2;
				counter = 20;
				DustFrame = 1;
				xca = -1;
				xcb = -1;
				xcc = -1;
				xcd = -1;
				xce = -1;
				yca = -1;
				ycb = -1;
				ycc = -1;
				ycd = -1;
				yce = -1;
				Game->PlaySound(66); //Change/Disable SFX if needed

				while(counter > 0) {

					Link->Z = 0;
					Link->InputUp = false;
					Link->InputDown = false;
					Link->InputLeft = false;
					Link->InputRight = false;
					Link->InputA = false;
					Link->InputB = false;
					Link->InputR = false;
					Link->InputL = false;

					if(Floor(counter/2) == counter/2) { //trigger animation every other frame

						xce = xcd;
						xcd = xcc;
						xcc = xcb;
						xcb = xca;

						yce = ycd;
						ycd = ycc;
						ycc = ycb;
						ycb = yca;

						xca = Link->X;
						yca = Link->Y;

						if(DustFrame >= 5) {

							xca = -1;
							yca = -1;

						}

						DustFrame ++;

					}

					if(!(xca == -1) && !(yca == -1)) {Screen->DrawTile(2, xca, yca, DustTile, 1, 1, DustCSet, 1, 0, 0, 0, 0, true, 128);}
					if(!(xcb == -1) && !(ycb == -1)) {Screen->DrawTile(2, xcb, ycb, DustTile + 1, 1, 1, DustCSet, 1, 0, 0, 0, 0, true, 128);}
					if(!(xcc == -1) && !(ycc == -1)) {Screen->DrawTile(2, xcc, ycc, DustTile + 2, 1, 1, DustCSet, 1, 0, 0, 0, 0, true, 128);}
					if(!(xcd == -1) && !(ycd == -1)) {Screen->DrawTile(2, xcd, ycd, DustTile + 3, 1, 1, DustCSet, 1, 0, 0, 0, 0, true, 128);}
					if(!(xce == -1) && !(yce == -1)) {Screen->DrawTile(2, xce, yce, DustTile + 4, 1, 1, DustCSet, 1, 0, 0, 0, 0, true, 128);}

					if(Link->Dir == DIR_UP) {

						if(!isSolid(Link->X+4, Link->Y+6) && !isSolid(Link->X+12, Link->Y+6) && (Screen->ComboF[ComboAt(Link->X+8, Link->Y+6)] != 98)) {Link->Y -= 2;}

					} else if(Link->Dir == DIR_DOWN) {

						if(!isSolid(Link->X+4, Link->Y+18) && !isSolid(Link->X+12, Link->Y+18) && (Screen->ComboF[ComboAt(Link->X+8, Link->Y+18)] != 98)) {Link->Y += 2;}

					} else if(Link->Dir == DIR_LEFT) {

						if(!isSolid(Link->X-2, Link->Y+12) && (Screen->ComboF[ComboAt(Link->X-2, Link->Y+4)] != 98)) {Link->X -= 2;}

					} else if (Link->Dir == DIR_RIGHT) {

						if(!isSolid(Link->X+18, Link->Y+12) && (Screen->ComboF[ComboAt(Link->X+18, Link->Y+4)] != 98)) {Link->X += 2;}

					} //end if

				counter --;
				justRolled = true;

				Waitframe();

				} //end while

			} //end if

		if(justRolled) {

			Link->Jump = 0;
			justRolled = false;

		}

		Link->InputL = false;

		Waitframe();

		} //end while

	} //end void run

} //end script
Notes:

*It's a global script, so there are no parameters and it cannot be disabled without another script.
*By default, L is used to roll. To change it, replace InputL with InputR and vice-versa.
*It is customizable by the options at the top. You can change the CSet and Starting dust "kick up" tile. You can also change the sound effect. It is SFX #66 by default.
*You can roll through layers if you don't mark them with flag 98.
*Mark anything you don't want roll-onto-able on layer 0 with flag 98. G'head. Use it. That's what the general purpose flags are for!
*You can roll over warps, so be careful with cutscenes by marking the tiles ahead of the pits/warps with flag 98s.
*You need jump tiles for this to work. And your jump tiles must be of the rolling variety.
*As of now, the collision detection isn't very accurate, so if there is any unwalkable part of the tile, you cannot roll through it. This is no longer true. It now goes down to the quarter-combo.
*It really is a psudo-roll. You actually do a jump that brings you to Z = 0 each frame and moves you forward if possible.
*You'll probably want the "poof" tiles or similar for the dust "kick up."
*the dust "kick up" is at a fixed 5-frame animation. If you want more frames, you'll have to edit the script. If you want less, leave blanks at the end of the animation
*You can't perform anything else during a roll.
*I forgot to mention this before, but it is designed for the smaller Link hitbox. To enable it for the large hitbox, change the +6s to -2s on the up rolling fork and add !isSolid(Link->X-2, Link->Y+4) to the left fork and !isSolid(Link->X+18, Link->Y+4) to the right DIR fork.

EDIT: Due to the new allocation of general purpose flags I changed flag 97 to flag 98! Thankfully, I don't have a whole lot to change in AMN to make it consistent. You WILL have to painstakingly change every last flag 97 to a flag 98. With the improved collision detection, it is now sensitive down to the quarter-combo!