diff --git a/include/link_handler.h b/include/link_handler.h index f90838d..cffc44f 100644 --- a/include/link_handler.h +++ b/include/link_handler.h @@ -130,7 +130,7 @@ enum CompositeState { NO_COMPOSITE_STATE, INITIAL_CONNECTION, - GET_BOX_LIST, + PACKET_EXCHANGE, }; enum SubstateState @@ -152,7 +152,9 @@ enum SubstateState SEND_SPECIFIC_PAYLOAD, SOFT_RESET, - // GET_BOX_LIST + // PACKET_EXCHANGE + BYTE_EXCHANGE, + END, }; @@ -160,6 +162,33 @@ enum SubstateState enum LinkConnectionError { NO_ERROR, + PACKET_TIMED_OUT, +}; + +enum PayloadCommand +{ + CMD_ReloadCurrentBox, // no arguments used. Reloads the current box from SRAM. Use this as the first command byte before performing other commands. + CMD_TransferPokemon, // 1st argument = secondary payload size, 2nd argument = box that should be transferred from. This command uses a secondary payload. The size of this secondary payload needs to be declared beforehand. Prior to requesting a secondary payload, the program will use the second argument to load a specific box from SRAM. Box numbers are 0-indexed and range from 0x00 (box 1) to 0x0B(box 12). This load procedure currently cannot be skipped. Once the secondary payload arrives, the program will verify its integrity and align the payload. Afterwards, it will use the information within this payload to remove pokémon from the current box. Once all transferred pokémon have been removed, the program will save the current box. + CMD_SoftReset, // no arguments used. Instantly soft resets the game. + CMD_OpenSRAM, // 1st argument = SRAM bank to be opened. Opens access to SRAM and switches to the SRAM bank determined by the 1st argument. SRAM will remain open afterwards. + CMD_CloseSRAM, // no arguments used. Instantly closes access to SRAM. + CMD_RunSecondaryPayload, // 1st argument = secondary payload size. This command uses a secondary payload. The size of this secondary payload needs to be declared beforehand. Once the secondary payload arrives, the program will verify its integrity and align the payload. Afterwards, it will jump to the secondary payload and execute it. IMPORTANT: if you want to report an error when executing this secondary payload, return with carry flag set. IMPORTANT: if you want to report that the payload was executed safely, return with carry flag reset.*/ + CMD_ReadDataRequest, // a request to read data starting from the address defined by the 16-bit pointer. +}; + +#define OUT_PACKET_LENGTH 16 +#define IN_PACKET_LENGTH 16 + +struct LinkPacket +{ + // Out packet parameters + PayloadCommand command; + byte argument[2] = {0x00, 0x00}; + u16 pointer; + + // Incoming data + byte recievedData[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + LinkConnectionError latestError = NO_ERROR; }; class LinkConnection @@ -200,11 +229,15 @@ public: bool test_packet_fail = false; // ??? byte data_packet[PACKET_SIZE]; - byte curr_payload[0x2A0]; + byte payloadBuffer[0x2A0]; int curr_payload_size = 0; - byte dataOutBuffer[0xFF]; + byte dataOutBuffer[16]; int dataOutBufferCurrIndex = 0; + LinkPacket *currLinkPacketArr; + int currLinkPacketArrNum = 0; + int currLinkPacketArrIndex = 0; + bool paused = false; // Used for pausing and sending one byte at a time void setup(const u16 *debug_charset); @@ -219,6 +252,7 @@ private: void load_payload(GB_PayloadsFiles payload); void LoadCurrGameFromChecksum(); void logicState_initConnection(); + void logicState_packetExchange(); // Used for debug features #define LINE_WIDTH 24 diff --git a/source/link_handler.cpp b/source/link_handler.cpp index 25c0137..6ef8893 100644 --- a/source/link_handler.cpp +++ b/source/link_handler.cpp @@ -68,18 +68,27 @@ void LinkConnection::setup(const u16 *debug_charset) void LinkConnection::startConnection(CompositeState startState) { - nextCompState = startState; switch (startState) { case INITIAL_CONNECTION: - nextSubState = CLOCK; + subState = CLOCK; REG_TM3D = -0x4000 / 60; REG_TM3CNT = TM_FREQ_1024 | TM_ENABLE; - irq_enable(II_TIMER3); + break; + case PACKET_EXCHANGE: + subState = BYTE_EXCHANGE; + //REG_TM3D = -0x0040; + REG_TM3D = -0x4000 / 2; + REG_TM3CNT = TM_FREQ_1024 | TM_ENABLE; break; default: break; } + + nextSubState = subState; + nextCompState = startState; + lastError = NO_ERROR; + irq_enable(II_TIMER3); } void LinkConnection::exchangeBytes() @@ -138,11 +147,17 @@ void LinkConnection::writeData() void LinkConnection::handleStateLogic() { + subState = nextSubState; + compState = nextCompState; + switch (compState) { case INITIAL_CONNECTION: logicState_initConnection(); break; + case PACKET_EXCHANGE: + logicState_packetExchange(); + break; default: break; } @@ -168,18 +183,8 @@ void LinkConnection::handleStateLogic() compStateCounter++; compStateChanged = false; } - - subState = nextSubState; - compState = nextCompState; } -int test_packet[] = { - /* 1 preamble byte */ 0xFD, - /* 1 command byte */ 0x02, - /* 2 argument bytes */ 0x00, 0x00, - /* 1 16-bit pointer */ 0x00, 0x00, - /* 6 filler bytes */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - bool LinkConnection::earlyExit() { if (g_debug_options.print_link_data && key_hit(KEY_LEFT)) @@ -297,14 +302,15 @@ void LinkConnection::logicState_initConnection() nextSubState = WAIT_FOR_CHECKSUM_PAYLOAD; } } - outData = curr_payload[subStateCounter]; + outData = payloadBuffer[subStateCounter]; break; case MAIL: - if (subStateCounter >= 0x186) + if (subStateCounter > 0x186) { nextSubState = WAIT_FOR_CHECKSUM_PAYLOAD; } + outData = 0x00; break; case WAIT_FOR_CHECKSUM_PAYLOAD: @@ -350,7 +356,7 @@ void LinkConnection::logicState_initConnection() } if (subStateCounter < curr_payload_size) { - outData = curr_payload[subStateCounter]; + outData = payloadBuffer[subStateCounter]; } else { @@ -359,7 +365,116 @@ void LinkConnection::logicState_initConnection() break; case END: - irq_delete(II_TIMER3); + irq_disable(II_TIMER3); + break; + + default: + outData = inData; + break; + } +} + +void LinkConnection::logicState_packetExchange() +{ + switch (subState) + { + + /* + case SEND_PACKET: + + // Output the payload followed by 0xFF while waiting + if (subStateCounter > 12) + { + nextSubState = RECIEVE_PACKET; + } + outData = payloadBuffer[subStateCounter]; + break; + + case WAIT_FOR_RESPONSE: + if (inData != 0xFD) + { + nextSubState = RECIEVE_PACKET; + } + else if (subStateCounter >= 256) + { + lastError = PACKET_TIMED_OUT; + nextSubState = END; + } + outData = 0xFF; + break; + + case RECIEVE_PACKET: + // See if we've already begun recieving the response + if (dataOutBufferCurrIndex > 0) + { + // Are we at the end of the response? + if (dataOutBufferCurrIndex >= 13) + { + nextSubState = END; + } + else + { + dataOutBuffer[dataOutBufferCurrIndex] = inData; + dataOutBufferCurrIndex++; + } + } + // We haven't... see if this is the first byte in the response + + // Let's also make sure that we haven't been sitting here for a long time + + break; +*/ + + case BYTE_EXCHANGE: + + if (subStateCounter < OUT_PACKET_LENGTH) + { + // Start with OUT_PACKET_LENGTH of bytes of prep to make sure things are set to go + outData = 0xFF; + } + else + { + switch (subStateCounter % OUT_PACKET_LENGTH) + { + case 0: + outData = 0xFD; + break; + case 1: + outData = currLinkPacketArr[currLinkPacketArrIndex].command; + break; + case 2: + outData = currLinkPacketArr[currLinkPacketArrIndex].argument[0]; + break; + case 3: + outData = currLinkPacketArr[currLinkPacketArrIndex].argument[1]; + break; + case 4: + outData = currLinkPacketArr[currLinkPacketArrIndex].pointer >> 8; + break; + case 5: + outData = currLinkPacketArr[currLinkPacketArrIndex].pointer >> 0; + break; + case OUT_PACKET_LENGTH - 1: + currLinkPacketArrIndex++; + default: + outData = 0xFF; + break; + } + if (currLinkPacketArrIndex >= currLinkPacketArrNum) + { + nextSubState = END; + } + + if (subStateCounter % OUT_PACKET_LENGTH + 2 == 0) + { + // Process packet + } + dataOutBuffer[subStateCounter % OUT_PACKET_LENGTH + 2] = inData; + } + break; + + case END: + irq_disable(II_TIMER3); break; default: @@ -379,7 +494,7 @@ void LinkConnection::load_payload(GB_PayloadsFiles payload) reader.init(decompressionBuffer, sizeof(decompressionBuffer)); fileSize = reader.getFileSize(fileIndex); reader.seekToFile(fileIndex); - reader.read(this->curr_payload, fileSize); + reader.read(this->payloadBuffer, fileSize); this->curr_payload_size = fileSize; } diff --git a/source/script_array.cpp b/source/script_array.cpp index 08ef400..c686e09 100644 --- a/source/script_array.cpp +++ b/source/script_array.cpp @@ -793,12 +793,28 @@ bool run_conditional(int index) obj_unhide(flag, 0); obj_set_pos(flag, 1.5 * 8, 14 * 8); - - //globalLinkCable.startConnection(INITIAL_CONNECTION); + LinkPacket packets[6] = { + {CMD_ReadDataRequest, 0x00, 0x00, 0xDCC5}, + {CMD_ReadDataRequest, 0x00, 0x00, 0xDCC5}, + {CMD_ReadDataRequest, 0x00, 0x00, 0xDCC5}, + {CMD_ReadDataRequest, 0x00, 0x00, 0xDCC5}, + {CMD_ReadDataRequest, 0x00, 0x00, 0xDCC5}, + {CMD_ReadDataRequest, 0x00, 0x00, 0xDCC5}, + + }; + globalLinkCable.paused = true; while (true) { - VBlankIntrWait(); + globalLinkCable.currLinkPacketArr = packets; + globalLinkCable.currLinkPacketArrNum = 6; + globalLinkCable.currLinkPacketArrIndex = 0; + + globalLinkCable.startConnection(PACKET_EXCHANGE); + while (globalLinkCable.subState != END) + { + VBlankIntrWait(); + } } } reload_textbox_background();