diff --git a/.gitignore b/.gitignore index b27679d..b5b50ba 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,9 @@ .vscode/ *.bin *.line +*.egg *.cm __pycache__/ venv/ -sprites/ \ No newline at end of file +sprites/ +eggs/ \ No newline at end of file diff --git a/linecreator/create_line.py b/linecreator/create_line.py index 2503d7a..5fda2e1 100644 --- a/linecreator/create_line.py +++ b/linecreator/create_line.py @@ -2,18 +2,19 @@ import re import sys import logging -def process_npet_file(origFp, outputName): +def process_npet_file(origFp, eggFp, outputName): file_header = origFp.readline() - matches = re.findall(r"\[\s*([0-9a-fA-F]+)\s*\|\s*([^|]+?)\s*\|\s*([0-9a-fA-F]+)\s*\]", file_header) + matches = re.findall(r"\[\s*([0-9a-fA-F]+)\s*\|\s*([^|]+?)\s*\|\s*([0-9a-fA-F]+)\s*\|\s*([0-9a-fA-F]+)\s*\]", file_header) - if len(matches[0]) != 3: + if len(matches[0]) != 4: logging.error("Cabecera invalida") return - id, nombre, numChara = matches[0] + id, nombre, numChara, hatchTime = matches[0] id = int(id, 16) numChara = int(numChara, 16) + hatchTime = int(hatchTime, 16) logging.info(f"Encontrado cabecera id={id}, nombre={nombre}, numchara={numChara}") @@ -23,6 +24,12 @@ def process_npet_file(origFp, outputName): destFp.write(id.to_bytes(1, "big")) destFp.write(nombre.encode("utf8").ljust(16, b"\0")) + + eggSpriteData = eggFp.read() + + destFp.write(eggSpriteData) + + destFp.write(hatchTime.to_bytes(2, "big")) destFp.write(numChara.to_bytes(1, "big")) for i in range(numChara): @@ -104,7 +111,7 @@ def process_nevo_file(origFp, outputName): destFp = open(outputName, "wb") destFp.write(b"NEVO") - + destFp.write(id.to_bytes(1, "big")) destFp.write(length.to_bytes(1, "big")) @@ -163,7 +170,10 @@ if __name__ == "__main__": header = origFp.readline() if "NPET" in header: logging.info("Cabecera NPET encontrada!") - process_npet_file(origFp, newFile) + origFileName = "".join(origFile.split(".")[0:-1]) + ".egg" + eggFp = open(origFileName, "rb") + process_npet_file(origFp, eggFp, newFile) + eggFp.close() elif "NEVO" in header: logging.info("Cabecera NEVO encontrada!") diff --git a/platformio.ini b/platformio.ini index f132cd9..2b474d1 100644 --- a/platformio.ini +++ b/platformio.ini @@ -12,8 +12,6 @@ platform = espressif32 board = esp32dev framework = arduino -upload_port = /dev/ttyUSB0 -upload_speed = 921600 monitor_speed = 115200 monitor_port = /dev/ttyUSB0 monitor_filters = esp32_exception_decoder diff --git a/scripts/png_to_rgb565.py b/scripts/png_to_rgb565.py index 3521d9a..81fc5ba 100644 --- a/scripts/png_to_rgb565.py +++ b/scripts/png_to_rgb565.py @@ -22,7 +22,6 @@ def split_image(filename: str) -> list[bytearray]: h = y + 16 tile = image.crop((x, y, w, h)) - tile.save(f"tile_{i}.png") tiles.append(tile) diff --git a/src/defs/chara_data.h b/src/defs/chara_data.h index 7f8e047..7b1ac13 100644 --- a/src/defs/chara_data.h +++ b/src/defs/chara_data.h @@ -7,11 +7,20 @@ struct CharacterData { // Calculated at runtime uint8_t hunger; uint8_t strength; - uint8_t effort; - uint8_t careMistakes; uint8_t weight; uint8_t age; uint8_t poopNumber; + + uint8_t careMistakes; + uint8_t effort; + uint8_t overfeed; + uint8_t sleepDisturbances; + + uint16_t stageTotalBattled; + uint16_t stageTotalWon; + + uint16_t charaTotalBattled; + uint16_t charaTotalWon; int32_t sleepCareMistakeCounter = 0; int32_t evoLeftTimer; @@ -30,12 +39,14 @@ struct CharacterData { bool dead = false; // Obtained from structure - uint8_t idLine; uint8_t idChara; + char charaName[40]; + uint8_t hp; uint8_t ap; uint8_t bp; + uint8_t stage; uint8_t attribute; @@ -45,6 +56,7 @@ struct CharacterData { uint32_t evoTime; uint16_t initialStatsReductionTime = 600; + uint8_t minWeight; }; #endif \ No newline at end of file diff --git a/src/defs/file_chara.h b/src/defs/file_chara.h new file mode 100644 index 0000000..25c5732 --- /dev/null +++ b/src/defs/file_chara.h @@ -0,0 +1,53 @@ +#ifndef FILE_CHARA_H +#define FILE_CHARA_H + +#include +#include "sprite_data.h" + +struct Egg_t { + uint8_t id; + char fileName[20]; + char name[16]; + SpriteData eggSprite; +}; + +typedef struct __attribute__((packed)) { + uint8_t id; + char name[16]; + uint8_t hp, ap, bp; + uint8_t stage; + uint8_t attribute; + uint8_t attackSprite; + uint32_t sleepTime; + uint32_t wakeTime; + uint32_t changeTime; + uint16_t depleteTime; + uint8_t minWeight; +} LineChara_t; + + +typedef struct __attribute__((packed)) { + uint8_t currentChara, nextChara; + uint8_t minCareMistake, maxCareMistake; + uint8_t minSleepDist, maxSleepDist; + uint8_t minOverfeeds, maxOverfeeds; + uint8_t minTraining, maxTraining; + uint8_t totalBattles, wonBattles; +} CareMistakes_t; + + +struct LineCare_t { + uint8_t lineId; + uint8_t numCareMistakesData; + CareMistakes_t* careMistakeData; +}; + +struct Line_t { + uint8_t id; + char name[16]; + uint8_t charaNumber; + uint16_t hatchTime; + LineChara_t* characters; +}; + +#endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 6f986f6..d01c91b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,6 +10,7 @@ #include "buttons/buttons.h" #include "vpet/vpet.h" #include "vpet/steps/steps.h" +#include "vpet/lines/lines.h" const char* TAG = "[MAIN]"; @@ -44,7 +45,7 @@ void secondCoreTask(void*); void setup() { Serial.begin(115200); delay(100); // Give MPU6050 and ESP32 time to power up - + Wire.begin(MPU_SDA_PIN, MPU_SCL_PIN); // I2C init before MPU6050 mpu.initialize(); @@ -59,8 +60,6 @@ void setup() { storage_initBackground("/bg.bin", bg); - debug_printFreeMemory(); - pinMode(K1_PIN, INPUT_PULLUP); pinMode(K2_PIN, INPUT_PULLUP); pinMode(K3_PIN, INPUT_PULLUP); @@ -75,6 +74,12 @@ void setup() { charaData.strengthCareMistakeTimer = 60; xTaskCreatePinnedToCore(secondCoreTask, "VPET_EVAL", 4096, NULL, 0, &secondLoop, 0); + + debug_printFreeMemory(); + + lines_testLines(); // REMOVE + + debug_printFreeMemory(); } diff --git a/src/vpet/evolutiom/evolution.cpp b/src/vpet/evolutiom/evolution.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/vpet/evolutiom/evolution.h b/src/vpet/evolutiom/evolution.h new file mode 100644 index 0000000..e69de29 diff --git a/src/vpet/lines/get_available_lines.cpp b/src/vpet/lines/get_available_lines.cpp new file mode 100644 index 0000000..3907026 --- /dev/null +++ b/src/vpet/lines/get_available_lines.cpp @@ -0,0 +1,106 @@ +#include "lines.h" +#include "memory/memory.h" + +#include "SPIFFS.h" + +const char lineHeader[5] = "NPET"; +const uint8_t headerSize = 4; + +struct Egg_t* lines_getAvailableLines(uint8_t* count) { + File root = SPIFFS.open("/lines"); + File lineFile = root.openNextFile(); + + uint8_t allocCount = 0; + char header[5]; + + while (lineFile) { + printf("[LINES] Opening file %s\n", lineFile.name()); + + uint8_t readBytes = lineFile.readBytes(header, headerSize); + if (strncmp(header, lineHeader, headerSize) == 0 && readBytes == headerSize) { + allocCount++; + } + + lineFile = root.openNextFile(); + } + + struct Egg_t* availableLines = (struct Egg_t*) malloc(sizeof(struct Egg_t) * allocCount); + + root.close(); + + printf("[LINES] Found %i lines.\n", allocCount); + allocCount = 0; + + root = SPIFFS.open("/lines"); + lineFile = root.openNextFile("r"); + + while (lineFile) { + uint16_t bytesRead = lineFile.readBytes(header, headerSize); + bytesRead += lineFile.read(&availableLines[allocCount].id, 1); + bytesRead += lineFile.readBytes(availableLines[allocCount].name, 16); + + bytesRead += lineFile.read(&availableLines[allocCount].eggSprite.spriteWidth, 1); + bytesRead += lineFile.read(&availableLines[allocCount].eggSprite.spriteHeight, 1); + bytesRead += lineFile.read(&availableLines[allocCount].eggSprite.spriteNumber, 1); // Se coloca el cursor al principio de los datos de sprite + + availableLines[allocCount].eggSprite.spriteNumber = 1; // Inutil, pero es que necesito hacer la lectura + + availableLines[allocCount].eggSprite.spriteData = memory_allocate( + availableLines[allocCount].eggSprite.spriteNumber, + availableLines[allocCount].eggSprite.spriteWidth, + availableLines[allocCount].eggSprite.spriteHeight + ); + + uint8_t highByte; + uint8_t lowByte; + + for (int i = 0; i < availableLines[allocCount].eggSprite.spriteWidth * availableLines[allocCount].eggSprite.spriteHeight; i++) { + bytesRead += lineFile.read(&highByte, 1); + bytesRead += lineFile.read(&lowByte, 1); + + uint16_t pixel = (highByte << 8) | lowByte; + + availableLines[allocCount].eggSprite.spriteData[0][i] = pixel; + } + + strcpy(availableLines[allocCount].fileName, lineFile.name()); + + lineFile.close(); + + allocCount++; + lineFile = root.openNextFile(); + } + + root.close(); + + *count = allocCount; + return availableLines; +} + +void lines_testLines() { + uint8_t countedLines; + struct Egg_t* availableLines = lines_getAvailableLines(&countedLines); + + char fullPath[8 + strlen(availableLines[0].fileName)]; + snprintf(fullPath, 20, "/lines/%s", availableLines[0].fileName); + + lines_freeEggList(availableLines, countedLines); + + printf("[DEBUG] fullPath=%s\n", fullPath); + + availableLines = (Egg_t*) malloc(sizeof(Egg_t)); + + struct Line_t* singleLine = lines_getSingleLine(fullPath, availableLines); + + lines_freeEggList(availableLines, 1); + + struct LineCare_t* lineCareData = lines_getLineCareMistakes(availableLines->fileName); + + for (int i = 0; i < lineCareData->numCareMistakesData; i++) { + printf( + "[DEBUG] Chara %d changes into chara %d\n", + lineCareData->careMistakeData[i].currentChara, + lineCareData->careMistakeData[i].nextChara + ); + } +} \ No newline at end of file diff --git a/src/vpet/lines/get_care_mistakes.cpp b/src/vpet/lines/get_care_mistakes.cpp new file mode 100644 index 0000000..940c40b --- /dev/null +++ b/src/vpet/lines/get_care_mistakes.cpp @@ -0,0 +1,30 @@ +#include "lines.h" +#include "defs/file_chara.h" + +#include "SPIFFS.h" + +struct LineCare_t* lines_getLineCareMistakes(const char* fileName) { + char careMistakesPath[strlen(fileName) + 8]; + snprintf(careMistakesPath, strlen(fileName) + 8, "/care/%s", fileName); + + File careMistakesFile = SPIFFS.open(careMistakesPath); + + uint8_t bytesRead = 0; + + LineCare_t* careMistakesData = (LineCare_t*) malloc(sizeof(LineCare_t)); + + careMistakesFile.seek(4, SeekCur); + + bytesRead += careMistakesFile.read(&careMistakesData->lineId, 1); + bytesRead += careMistakesFile.read(&careMistakesData->numCareMistakesData, 1); + + careMistakesData->careMistakeData = (CareMistakes_t*) malloc( + sizeof(CareMistakes_t) * careMistakesData->numCareMistakesData + ); + + for (int i = 0; i < careMistakesData->numCareMistakesData; i++) { + bytesRead += careMistakesFile.read((uint8_t*) &careMistakesData->careMistakeData[i], sizeof(CareMistakes_t)); + } + + return careMistakesData; +} \ No newline at end of file diff --git a/src/vpet/lines/get_single_line.cpp b/src/vpet/lines/get_single_line.cpp new file mode 100644 index 0000000..b828658 --- /dev/null +++ b/src/vpet/lines/get_single_line.cpp @@ -0,0 +1,86 @@ +#include "lines.h" +#include "memory/memory.h" + +#include + +struct Line_t* lines_getSingleLine(const char* fileName, Egg_t* selectedEgg) { + File lineFile = SPIFFS.open(fileName); + + struct Line_t* selectedLine = (struct Line_t*) malloc(sizeof(struct Line_t)); + if (selectedLine == NULL) { + printf("[LINES] Fallo reserva\n"); + } + + uint8_t buffer[4]; + + lineFile.seek(4, SeekCur); + + uint8_t bytesRead = lineFile.read(&selectedLine->id, 1); + bytesRead += lineFile.readBytes(selectedLine->name, 16); + + lines_getSingleEggSprites(lineFile, selectedEgg); + + bytesRead += lineFile.read(buffer, 2); + selectedLine->hatchTime = (buffer[0] << 8) | buffer[1]; + + bytesRead += lineFile.read(&selectedLine->charaNumber, 1); + + printf("[DEBUG] SelectedLine numChara=%d hatchTime=%d\n", selectedLine->charaNumber, selectedLine->hatchTime); + + selectedLine->characters = (LineChara_t*) malloc(selectedLine->charaNumber * sizeof(LineChara_t)); + + for (int i = 0; i < selectedLine->charaNumber; i++) { + bytesRead += lineFile.read((uint8_t*) &selectedLine->characters[i], sizeof(LineChara_t)); + } + + return selectedLine; +} + +void lines_getSingleEggSprites(File &lineFile, Egg_t* selectedEgg) { + // Ahora si, vamos a ver cuantos sprites hay que reservar + + // Importante tener el nombre de archivo del huevo en todo momento + strcpy(selectedEgg->fileName, lineFile.name()); + + // Ahora se lee los datos + lineFile.read(&(selectedEgg->eggSprite.spriteWidth), 1); + lineFile.read(&(selectedEgg->eggSprite.spriteHeight), 1); + lineFile.read(&(selectedEgg->eggSprite.spriteNumber), 1); + + selectedEgg->eggSprite.spriteData = memory_allocate( + selectedEgg->eggSprite.spriteNumber, + selectedEgg->eggSprite.spriteWidth, + selectedEgg->eggSprite.spriteHeight + ); + + uint16_t size = selectedEgg->eggSprite.spriteWidth * selectedEgg->eggSprite.spriteHeight; + + uint8_t highByte; + uint8_t lowByte; + + for (int spr = 0; spr < selectedEgg->eggSprite.spriteNumber; spr++) { + for (int i= 0; i < size; i++) { + lineFile.read(&highByte, 1); + lineFile.read(&lowByte, 1); + + uint16_t pixel = (highByte << 8) | lowByte; + + selectedEgg->eggSprite.spriteData[spr][i] = pixel; + } + } +} + +// Son las 22:35, que estoy haciendo? +// Pues claro + +void lines_freeEggList(Egg_t* eggList, uint8_t eggNumber) { + for (int i = 0; i < eggNumber; i++) { + for (int j = 0; j < eggList[i].eggSprite.spriteNumber; j++) { + free(eggList[i].eggSprite.spriteData[j]); + } + + free(eggList[i].eggSprite.spriteData); + } + + free(eggList); +} \ No newline at end of file diff --git a/src/vpet/lines/lines.h b/src/vpet/lines/lines.h new file mode 100644 index 0000000..23a7dd9 --- /dev/null +++ b/src/vpet/lines/lines.h @@ -0,0 +1,14 @@ +#ifndef LINES_H +#define LINES_H + +#include "defs/file_chara.h" +#include + +struct Egg_t* lines_getAvailableLines(uint8_t* count); +struct Line_t* lines_getSingleLine(const char* fileName, Egg_t* eggList); +void lines_getSingleEggSprites(fs::File &lineFile, Egg_t* eggList); +void lines_freeEggList(Egg_t* eggList, uint8_t eggNumber); +struct LineCare_t* lines_getLineCareMistakes(const char* fileName); +void lines_testLines(); + +#endif \ No newline at end of file