How do I randomly generate a top-down 2D level with separate sections and is infinite?

I've read many other questions/answers about random level generation but most of them deal with either randomly/proceduraly generating 2D levels viewed from the side or 3D levels. What I'm trying to achieve is sort of like you were looking straight down on a Minecraft map. There is no height, but the borders of each "biome" or "section" of the map are random and varied. I already have basic code that can generate a perfectly square level with the same tileset (randomly picking segments from the tileset image), but I've encountered a major issue for wanting the level to be infinite: Beyond a certain point, the tiles' positions become negative on one or both of the axis. The code I use to only draw tiles the player can see relies on taking the tiles position and converting it to the index number that represents it in the array. As you well know, arrays cannot have a negative index. Here is some of my code:

This generates the square (or rectangle) of tiles:

//Scale is in tiles
public void Generate(int sX, int sY)
{
scaleX = sX;
scaleY = sY;

for (int y = 0; y <= scaleY; y++)
{

for (int x = 0; x <= scaleX; x++)
{
tiles[tiles.Count - 1].Add(tileset.randomTile(x * tileset.TileSize, y * tileset.TileSize));
}
}
}

Before I changed the code after realizing an array index couldn't be negative my for loops looked something like this to center the map around (0, 0):

for (int y = -scaleY / 2; y <= scaleY / 2; y++)
for (int x = -scaleX / 2; x <= scaleX / 2; x++)

Here is the code that draws the tiles:

int startX = (int)Math.Floor((player.Position.X - (graphics.Viewport.Width) - tileset.TileSize) / tileset.TileSize);
int endX = (int)Math.Ceiling((player.Position.X + (graphics.Viewport.Width) + tileset.TileSize) / tileset.TileSize);
int startY = (int)Math.Floor((player.Position.Y - (graphics.Viewport.Height) - tileset.TileSize) / tileset.TileSize);
int endY = (int)Math.Ceiling((player.Position.Y + (graphics.Viewport.Height) + tileset.TileSize) / tileset.TileSize);

for (int y = startY; y < endY; y++)
{
for (int x = startX; x < endX; x++)
{
if (x >= 0 && y >= 0 && x <= scaleX && y <= scaleY)
tiles[y][x].Draw(spriteBatch);
}
}

So to summarize what I'm asking: First, how do I randomly generate a top-down 2D map with different sections (not chunks per se, but areas with different tile sets) and second, how do I get past this negative array index issue?