#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
//#include <bits/stdc++.h>

typedef long double ld;
using ll = long long;
const ll INF = (ll)1e18;
const ll MOD = 1e9 + 7;

ll H, W, V;
ll sy, sx, gy, gx;
ll dy[4] = { 0,  0, -1, +1};
ll dx[4] = {-1, +1,  0,  0};

// Output
template<class T, class S> std::ostream& operator << (std::ostream& os, std::pair<T, S> p)
{
  return os << "(" << p.first << " " << p.second << ")";
}

template<class T> std::ostream& operator << (std::ostream& os, std::vector< T > v)
{
  for (ll i = 0; i < (ll)v.size(); i++){ os << " [" << i << "]" << v[i]; if (i % 10 == 9) os << std::endl; }
  //os << v[0]; for (ll i = 1; i < (ll)v.size(); i++){ os << " " << v[i]; }
  return os;
}

template<class T, class S> std::ostream& operator << (std::ostream& os, std::map< T, S > m)
{
  ll i = 0; for (auto p : m){ os << " [" << i << "]" << p.first << "->" << p.second; i++;}
  return os;
}

void print(){ std::cout << std::endl; }
template <typename Head> void print(Head&& head) { std::cout << head << std::endl; }
template <typename Head, typename... Tail> void print(Head&& head, Tail&&... tail)
{
  std::cout << head << " ";
  print(std::forward<Tail>(tail)...); // or print(tail...);
}


ll pos2idx(ll y, ll x) { return y * W + x; }
ll idx2y(ll idx) { return idx / W; }
ll idx2x(ll idx) { return idx % W; }

typedef struct {
  ll from;
  ll to;
  ll cost;
} S_Edge;

void research_grid(std::vector< std::string >& grid, std::vector< std::vector< S_Edge > >& vedge)
{
  for (ll y = 0; y < H; y++) {
    for (ll x = 0; x < W; x++) {
      for (ll d = 0; d < 4; d++) {
	ll ny = y + dy[d];
	ll nx = x + dx[d];
	ll from = pos2idx( y,  x);
	ll to   = pos2idx(ny, nx);
	if (ny >= 0 && nx >= 0 && ny < H && nx < W) {
	  S_Edge edge;
	  edge.from = from;
	  edge.to   = to;
	  edge.cost = grid[ny][nx] == '#' ? INF : 1;
	  vedge[from].push_back(edge);
	}
      }
    }
  }
}

void research_grid2(std::vector< std::string >& grid, std::vector< std::vector< ll > >& warshall_dist)
{
  for (ll y = 0; y < H; y++) {
    for (ll x = 0; x < W; x++) {
      ll from = pos2idx( y,  x);
      warshall_dist[from][from] = 0LL;
      for (ll d = 0; d < 4; d++) {
	ll ny = y + dy[d];
	ll nx = x + dx[d];
	ll to   = pos2idx(ny, nx);
	if (ny >= 0 && nx >= 0 && ny < H && nx < W) {
	  warshall_dist[from][to] = grid[ny][nx] == '#' ? INF : 1;
	}
      }
    }
  }
}

void research_grid3(std::vector< std::string >& grid, std::vector< S_Edge >& vedge)
{
  for (ll y = 0; y < H; y++) {
    for (ll x = 0; x < W; x++) {
      for (ll d = 0; d < 4; d++) {
	ll ny = y + dy[d];
	ll nx = x + dx[d];
	ll from = pos2idx( y,  x);
	ll to   = pos2idx(ny, nx);
	if (ny >= 0 && nx >= 0 && ny < H && nx < W) {
	  S_Edge edge;
	  edge.from = from;
	  edge.to   = to;
	  edge.cost = grid[ny][nx] == '#' ? INF : 1;
	  vedge.push_back(edge);
	}
      }
    }
  }
}


ll get_distance_dijkstra(std::string& idx_grid, std::vector< std::vector< S_Edge > >& vedge)
{
  std::vector<ll> dist(V, INF);
  ll s = pos2idx(sy, sx);
  ll g = pos2idx(gy, gx);

  dist[s] = 0LL;
  typedef std::pair<ll, ll> P;
  std::priority_queue<P, std::vector<P>, std::greater<P> > que;
  que.push(P(dist[s], s));
  while (!que.empty()) {
    P p = que.top(); que.pop();
    ll v = p.second;
    for (auto edge : vedge[v]) {
      if (dist[edge.to] > dist[edge.from] + edge.cost) {
	dist[edge.to] = dist[edge.from] + edge.cost;
	que.push(P(dist[edge.to], edge.to));
      }
    }
  }

  return dist[g];
}

ll get_distance_warshallFloyd(std::string& idx_grid, std::vector< std::vector< ll > >& dist)
{
  ll s = pos2idx(sy, sx);
  ll g = pos2idx(gy, gx);

  for (ll k = 0; k < V; k++)
    for (ll i = 0; i < V; i++)
      for (ll j = 0; j < V; j++)
	dist[i][j] = std::min(dist[i][j], dist[i][k] + dist[k][j]);

  return dist[s][g];
}

ll get_distance_bellmanFord(std::string& idx_grid, std::vector< S_Edge >& vedge)
{
  std::vector<ll> dist(V, INF);
  ll s = pos2idx(sy, sx);
  ll g = pos2idx(gy, gx);

  dist[s] = 0LL;
  while(1) {
    bool was_updated = false;

    for (auto it = vedge.begin(); it != vedge.end(); it++) {
      if (dist[it->to] > dist[it->from] + it->cost) {
	dist[it->to] = dist[it->from] + it->cost;
	was_updated = true;
      }
    }
    if (!was_updated) {
      break;
    }
  }

  return dist[g];
}

ll get_distance_bfs(std::string& idx_grid, std::vector< std::vector< S_Edge > >& vedge)
{
  std::vector<ll> dist(V, INF);
  std::queue<ll> que;
  ll s = pos2idx(sy, sx);
  ll g = pos2idx(gy, gx);

  dist[s] = 0LL;
  que.push(s);
  while (!que.empty()) {
    ll v = que.front(); que.pop();
    for (auto edge : vedge[v]) {
      if (dist[edge.to] > dist[edge.from] + edge.cost) {
	dist[edge.to] = dist[edge.from] + edge.cost;
	que.push(edge.to);
      }
    }
  }
  return dist[g];
}

int main()
{
  std::cin >> H >> W;
  sy--; sx--; gy--; gx--;
  sy = 0LL;
  sx = 0LL;
  gy = H - 1;
  gx = W - 1;
  V = H * W;

  std::vector< std::string > grid(H, std::string(W, 'x'));
  std::string idx_grid;

  ll cnt = 0LL;
  for (ll y = 0; y < H; y++) {
    for (ll x = 0; x < W; x++) {
      std::cin >> grid[y][x];
      if (grid[y][x] == '#') cnt++;
    }
    idx_grid += grid[y];
  }

  std::vector< ll > dist(V, INF);
  std::vector< std::vector<S_Edge> > G(V);
  for (ll y = 0; y < H; y++) {
    for (ll x = 0; x < W; x++) {
      for (ll d = 0; d < 4; d++) {
	ll ny = y + dy[d];
	ll nx = x + dx[d];
	if (ny >=0 && nx >= 0 && ny < H && nx < W ) {
	  S_Edge edge;
	  edge.from = pos2idx(y,x);
	  edge.to   = pos2idx(ny,nx);
	  edge.cost = grid[ny][nx] == '.' ? 1LL : INF;
	  G[pos2idx(y,x)].push_back(edge);
	}
      }
    }
  }

  typedef std::pair<ll, ll> P;
  std::priority_queue< P, std::vector<P>, std::greater<P> > que;
  dist[pos2idx(sy, sx)] = 0LL;
  que.push({0LL, pos2idx(sy, sx)});
  while (!que.empty()) {
    P p = que.top(); que.pop();
    ll v = p.second;
    for (auto edge : G[v]) {
      if (dist[edge.to] > dist[edge.from] + edge.cost) {
	dist[edge.to] = dist[edge.from] + edge.cost;
	que.push({dist[edge.to], edge.to});
      }
    }
  }

  ll ans = INF;
  if (dist[pos2idx(gy,gx)] == INF) {
    print(-1);
    return 0;
  }

  ans = V - dist[pos2idx(gy,gx)] - 1 - cnt;
  print(ans);

  return 0;
}


Measured memory_bytes: 640