#include <bits/stdc++.h>
using namespace std;
int64_t dp[1010][1010][3];
int64_t g[1010][1010];
const int64_t INF = 1e11;
int main() {
// 左边来
// dp[i][j][0] = max(dp[i][j-1][0], dp[i][j-1][1], dp[i][j-1][2]) + g[i][j]
// 上边来
// dp[i][j][1] = max(dp[i-1][j][0], dp[i-1][j][1]) + g[i][j]
// 下边来
// dp[i][j][2] = max(dp[i+1][j][0], dp[i+1][j][2]) + g[i][j]
int m, n;
scanf("%d%d", &m, &n);
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
scanf("%lld", &g[i][j]);
}
}
dp[0][0][0] = dp[0][0][1] = dp[0][0][2] = g[0][0];
for (int i = 1; i < n; ++i) {
dp[0][i][1] = dp[m-1][i][2] = -INF; // 第一行的上边来和最后一行的下边来是不行的
}
for (int i = 1; i < m; ++i) {
dp[i][0][0] = dp[i][0][2] = -INF; // 第一列的左边来和下边来是不行的, 因为一旦下边来了, 类似贪吃蛇, 会有交叉
dp[i][0][1] = dp[i-1][0][1] + g[i][0]; // 第一列只能上边来
}
// 到此, 已经计算出第一列的左边/上边/下边来, 下面考虑怎么计算后序列
for (int j = 1; j < n; ++j) {
// 计算顺序, 从左到右, 先计算同一列的左边来, 再从下往上计算同一列的下边来/从上往下计算同一列的上边来
for (int i = 0; i < m; ++i) {
// 可以发现, 左边来只依赖前一列的结果, 因此左边来可以计算, 由于下边来和上边来都依赖左边来, 因此必须先计算左边来
dp[i][j][0] = max(max(dp[i][j-1][0], dp[i][j-1][1]), dp[i][j-1][2]) + g[i][j];
if (i) {
// 上边来只依赖上一行且同一列的左边来和上边来, 因此在左边来计算出来后也可以计算
dp[i][j][1] = max(dp[i-1][j][0], dp[i-1][j][1]) + g[i][j];
}
}
for (int i = m - 2; i >= 0; --i) {
// 下边来只依赖下一行且同一列的下边来和左边来, 因此在左边来计算出来后也可以计算
dp[i][j][2] = max(dp[i+1][j][0], dp[i+1][j][2]) + g[i][j];
}
}
printf("%lld\n", max(dp[m-1][n-1][0], dp[m-1][n-1][1]));
return 0;
}