Not sure what I've done wrong...

Hi everyone,
I've done up this sketch:

#include <SPI.h>
#include <SD.h>
#include <FTOLED.h>

OLED oled(7, 2, 3);

#define imageWidth    63
#define imageHeight   63
#define MIN   1

boolean values[imageWidth][imageHeight];
boolean nextValues[imageWidth][imageHeight];

void setup() {
  oled.begin();
  oled.fillScreen(GREEN);
  delay(1000);
  oled.fillScreen(BLACK);
  
  randomSeed(analogRead(A0) * 10 + analogRead(A6) * 10);
  initialise();
}

void loop() {
  for(byte x = MIN; x < imageWidth; x++) {
    for(byte y = MIN; y < imageHeight; y++) {
      byte neighbourCount = 0;
      
      if(values[x - 1][y]) {
        neighbourCount++;
      }
      if(values[x][y - 1]) {
        neighbourCount++;
      }
      if(values[x - 1][y - 1]) {
        neighbourCount++;
      }
      if(values[x + 1][y]) {
        neighbourCount++;
      }
      if(values[x][y + 1]) {
        neighbourCount++;
      }
      if(values[x + 1][y + 1]) {
        neighbourCount++;
      }
      if(values[x - 1][y + 1]) {
        neighbourCount++;
      }
      if(values[x + 1][y - 1]) {
        neighbourCount++;
      }
      
      if((values[x][y] == HIGH) && (neighbourCount < 2)) {
        nextValues[x][y] = LOW;
      }
      if((values[x][y] == HIGH) && (neighbourCount == 2 || neighbourCount == 3)) {
        nextValues[x][y] = HIGH;
      }
      if((values[x][y] == HIGH) && (neighbourCount > 3)) {
        nextValues[x][y] = LOW;
      }
      if((values[x][y] == LOW) && (neighbourCount == 3)) {
        nextValues[x][y] = HIGH;
      }
      neighbourCount = 0;
    }
  }
  update();
}

void update() {
  for(byte x = MIN; x < imageWidth; x++) {
    for(byte y = MIN; y < imageHeight; y++) {
      if(nextValues[x][y]) {
        oled.setPixel(x, y, GREEN);
      }
      else {
        oled.setPixel(x, y, BLACK);
      }
    }
  }
  memcpy(values, nextValues, sizeof(values));
}

void initialise() {
  for(byte a = MIN; a < imageWidth; a++) {
    for(byte b = MIN; b < imageHeight; b++) {
      nextValues[a][b] = random(0, 129) % 2;
    }
  }
  update();
}

Which is Conway's Game of Life, a zero player game involving the interactions of cells and those around them.
I then upgraded the code to include a RAM module (because having two 128*128 arrays won't fit in the Arduino's RAM):

#include <SPI.h>
#include <SD.h>
#include <FTOLED.h>
#include <eRAM.h>

#define SS_PIN 5
eRAM ram(SS_PIN, SPI_CLOCK_DIV2);

OLED oled(7, 2, 3);

#define imageWidth    128
#define imageHeight   128
#define MIN   1


void setup() {  // initialise all the stuff
  Serial.begin(115200);
  ramClear();
  oled.begin();
  oled.fillScreen(GREEN);
  delay(1000);
  oled.fillScreen(BLACK);
  
  randomSeed(analogRead(A0) * 10 + analogRead(A6) * 10);
  initialise();
}

void loop() {
  for(int x = MIN; x < imageWidth; x++) {
    for(int y = MIN; y < imageHeight; y++) {
      int neighbourCount = 0;
      
     // checks if the cell has neighbours
      if(ramReadArrayA(x - 1, y)) {
        neighbourCount++;
      }
      if(ramReadArrayA(x, y - 1)) {
        neighbourCount++;
      }
      if(ramReadArrayA(x - 1, y - 1)) {
        neighbourCount++;
      }
      if(ramReadArrayA(x + 1, y)) {
        neighbourCount++;
      }
      if(ramReadArrayA(x, y + 1)) {
        neighbourCount++;
      }
      if(ramReadArrayA(x + 1, y + 1)) {
        neighbourCount++;
      }
      if(ramReadArrayA(x - 1, y + 1)) {
        neighbourCount++;
      }
      if(ramReadArrayA(x + 1, y - 1)) {
        neighbourCount++;
      }
      
      // decide if the cell will live or not based on its neighbours
      if((ramReadArrayA(x, y) == HIGH) && (neighbourCount < 2)) {
        ramWriteArrayB(x, y, LOW);
      }
      if((ramReadArrayA(x, y) == HIGH) && (neighbourCount == 2 || neighbourCount == 3)) {
        ramWriteArrayB(x, y, HIGH);
      }
      if((ramReadArrayA(x, y) == HIGH) && (neighbourCount > 3)) {
        ramWriteArrayB(x, y, LOW);
      }
      if((ramReadArrayA(x, y) == LOW) && (neighbourCount == 3)) {
        ramWriteArrayB(x, y, HIGH);
      }
      neighbourCount = 0;
    }
  }
  update();
}

void update() {   // update the display
  for(int x = MIN; x < imageWidth; x++) {
    for(int y = MIN; y < imageHeight; y++) {
      if(ramReadArrayB(x, y) == HIGH) {     // if the cell is alive
        oled.setPixel(x, y, GREEN);
      }
      else {
        oled.setPixel(x, y, BLACK);
      }
    }
  }
  ramCopyArrays();
}

void initialise() {
  for(int a = MIN; a < imageWidth; a++) {
    for(int b = MIN; b < imageHeight; b++) {
      int randomNum = 0;//random(0, 1234) % 2;
      if(randomNum == 1) {
        ramWriteArrayB(a, b, HIGH);
      }
      else {
        ramWriteArrayB(a, b, LOW);
      }
    }
  }
  ramWriteArrayB(16, 16, HIGH);
  ramWriteArrayB(16, 17, HIGH);
  ramWriteArrayB(17, 16, HIGH);
  ramWriteArrayB(17, 17, HIGH);
  
  update();
}

void ramClear() {
  for(long zxc = 0; zxc < 32768; zxc++) {
    ram.writebyte(zxc, 0);
  }
}

byte ramReadArrayA(long first, long second) {   // For reading bytes from the first array
  return ram.readbyte((second * imageWidth) + first);
}

void ramWriteArrayA(long first, long second, int data_value) {   // For writing bytes to the first array
  ram.writebyte((second * imageWidth) + first, data_value);
}

byte ramReadArrayB(long first, long second) {    // For reading bytes from the second array
  return ram.readbyte((second * imageWidth) + first + imageHeight);
}

void ramWriteArrayB(long first, long second, int data_value) {  // For writing bytes to the first array
  ram.writebyte((second * imageWidth) + first + imageHeight, data_value);
}

void ramCopyArrays() {
  for(long arrayIndexA = 0; arrayIndexA < imageWidth; arrayIndexA++) {
    for(long arrayIndexB = 0; arrayIndexB < imageHeight; arrayIndexB++) {
      ramWriteArrayA(arrayIndexA, arrayIndexB, ramReadArrayB(arrayIndexA, arrayIndexB));
    }
  }
}

Anyway, I am using a Freetronics EtherMega (just basically Arduino Mega 2560 with inbuilt ethernet), a Freetronics OLED screen (just an SPI screen), and a 23k256 SRAM module.
But none of those are the problem. They all work fine together, no problems with SPI or anything.
The problem is I am getting results I don't expect. I have put in the seed as a 22 square, which should just stay as a square forever. But it seems there is a "leak" and the screen starts displaying pixels "leaking" from the top-right corner of the cube. By leaking I mean pixels that should be "dead" are becoming "alive" when they shouldn't.
Now, I think I have the reading and writing from the arrays correct; my idea was to represent the arrays, despite being 2D, in a linear representation. So to find [a] you would go along b
size_of_a and then add a, and you would be at [a]. And to get to that same point but in array 2 (I have two arrays on the same "line") you would do the same but add size_of_a so you start at the start of the second array.
However if I am missing something here please do say so (it's quite likely I missed something there).
But otherwise I don't know why the code wouldn't be working, could anyone please inform me of what is wrong?
Thank you.
P.S. Oh I forgot to mention: disregard the fact that the imageWidth and imageHeight are different on each code that won't make any difference, just the first code doesn't have the RAM for 128128 so it has 6363.

Arduino booleans are bytes. If you packed those into bits the arrays would take 1/8th as much space.

Well, I could, but then that defeats the whole point of my question. What if I said I wanted to improve that to a 320240 display? Then it would require 2 320240 arrays, and even with your idea:
320*240 / 8 / 1024
Still equals more RAM than my Arduinos have.
So thank you but I would rather just fix the coding problem.

I'm not going to debug the sketch, don't have the energy but I do notice that in loop()

  for(byte x = MIN; x < imageWidth; x++) {
    for(byte y = MIN; y < imageHeight; y++) {
      byte neighbourCount = 0;
      
      if(values[x - 1][y]) {
        neighbourCount++;
      }
      if(values[x][y - 1]) {
        neighbourCount++;
      }
      if(values[x - 1][y - 1]) {
        neighbourCount++;
      }

you don't check edge conditions.

When x == MIN you still look for neighbors with an x - 1 coordinate.

Ah yes very good, however, that is why I define MIN as 1, so that it doesn't error when at coordinates [0][0]. Instead it starts at 1 to avoid problems and to keep the game running correctly.

But it seems there is a "leak" and the screen starts displaying pixels "leaking" from the top-right corner of the cube. By leaking I mean pixels that should be "dead" are becoming "alive" when they shouldn't.

Maybe you should define MAX?

Where exactly do you think I should use a MAX variable? Because where ever I need to restrict it, I just use imageWidth and ImageHeight because they are the dimensions of the array.
Is that what you mean, or am I not getting your point?

What data are you getting when you read x + 1 and/or y + 1 when x and/or y are at the array edge?

That's never a problem because the lowest value is MIN (which is 1) and the highest 127, and the array is 0 to 128. But even if that is a problem it doesn't matter because the first code works and the second is the same but with external ram and it doesn't work.
So array edges are not the problem because it worked fine the first time.

You seem to be using two SPI devices. Are they both using the same SPI settings, and unique slave select pins? If they aren't using the same settings, do you know that both libraries configure the SPI correctly before each operation?

Also, the the purposes of testing the RAM and display and compatibility between them I would use a test sketch that did the minimum necessary to show that each device worked, and leave out all the complexity of your real application - that's probably irrelevant, but we can't know that for sure until you eliminate it.

indeed:
That's never a problem because the lowest value is MIN (which is 1) and the highest 127, and the array is 0 to 128.

Wrong. The 128 element array is from 0 TO 127, NOT 128.

You shouldn't be making an (N+2) x (N+2) array to work on NxN elements let alone (N+1)x(N+1).
You should be writing exceptions for edge squares, using if-elseif-else statements.