public List<Trainer> getTrainers() {
		int traineroffset = romEntry.getValue("TrainerDataTableOffset");
		int traineramount = 47;
		int[] trainerclasslimits = romEntry.arrayEntries
				.get("TrainerDataClassCounts");

		int[] pointers = new int[traineramount + 1];
		for (int i = 1; i <= traineramount; i++) {
			int tPointer = readWord(traineroffset + (i - 1) * 2);
			pointers[i] = calculateOffset(bankOf(traineroffset), tPointer);
		}

		List<String> tcnames = getTrainerClassesForText();

		List<Trainer> allTrainers = new ArrayList<Trainer>();
		for (int i = 1; i <= traineramount; i++) {
			int offs = pointers[i];
			int limit = trainerclasslimits[i];
			String tcname = tcnames.get(i - 1);
			for (int trnum = 0; trnum < limit; trnum++) {
				Trainer tr = new Trainer();
				tr.offset = offs;
				tr.trainerclass = i;
				tr.fullDisplayName = tcname;
				int dataType = rom[offs] & 0xFF;
				if (dataType == 0xFF) {
					// "Special" trainer
					tr.poketype = 1;
					offs++;
					while (rom[offs] != 0x0) {
						TrainerPokemon tpk = new TrainerPokemon();
						tpk.level = rom[offs] & 0xFF;
						tpk.pokemon = pokes[pokeRBYToNumTable[rom[offs + 1] & 0xFF]];
						tr.pokemon.add(tpk);
						offs += 2;
					}
				} else {
					tr.poketype = 0;
					int fixedLevel = dataType;
					offs++;
					while (rom[offs] != 0x0) {
						TrainerPokemon tpk = new TrainerPokemon();
						tpk.level = fixedLevel;
						tpk.pokemon = pokes[pokeRBYToNumTable[rom[offs] & 0xFF]];
						tr.pokemon.add(tpk);
						offs++;
					}
				}
				offs++;
				allTrainers.add(tr);
			}
		}
		tagTrainersUniversal(allTrainers);
		if (romEntry.isYellow) {
			tagTrainersYellow(allTrainers);
		} else {
			tagTrainersRB(allTrainers);
		}
		return allTrainers;
	}