mirror of
https://github.com/Lorenzooone/Pokemon-Gen3-to-Gen-X.git
synced 2026-03-21 17:24:39 -05:00
162 lines
4.6 KiB
C
162 lines
4.6 KiB
C
#include "base_include.h"
|
|
#include "multiboot_handler.h"
|
|
#include "sio.h"
|
|
#include "menu_text_handler.h"
|
|
#include "print_system.h"
|
|
#include "timing_basic.h"
|
|
#include "useful_qualifiers.h"
|
|
|
|
#define MAX_PALETTE_ATTEMPTS 128
|
|
#define MULTIBOOT_WAIT_TIME_NS 36000
|
|
#define MULTIBOOT_VCOUNTWAIT (((MULTIBOOT_WAIT_TIME_NS/NS_PER_SCANLINE) + ((MULTIBOOT_WAIT_TIME_NS%NS_PER_SCANLINE) == 0 ? 0 : 1))+1)
|
|
|
|
void multiboot_send(int, int, u16*);
|
|
|
|
#ifndef HAS_SIO
|
|
void multiboot_send(int UNUSED(data), int UNUSED(is_normal), u16* UNUSED(out_buffer)) {
|
|
#else
|
|
void multiboot_send(int data, int is_normal, u16* out_buffer) {
|
|
// Only this part of REG_SIODATA32 is used during setup.
|
|
// The rest is handled by SWI $25
|
|
for(int i = 0; i < MAX_NUM_SLAVES; i++)
|
|
out_buffer[i] = 0;
|
|
if(is_normal)
|
|
out_buffer[0] = timed_sio_normal_master(data, SIO_32, MULTIBOOT_VCOUNTWAIT) >> 0x10;
|
|
else
|
|
timed_sio_multi_master(data, MULTIBOOT_VCOUNTWAIT, out_buffer);
|
|
#endif
|
|
}
|
|
|
|
#ifndef HAS_SIO
|
|
enum MULTIBOOT_RESULTS multiboot_normal (u16* UNUSED(data), u16* UNUSED(end), int UNUSED(is_normal)) {
|
|
#else
|
|
enum MULTIBOOT_RESULTS multiboot_normal (u16* data, u16* end, int is_normal) {
|
|
u16 response[MAX_NUM_SLAVES];
|
|
u8 clientMask = 0;
|
|
u8 client_bit;
|
|
int attempts, sends, halves;
|
|
u8 answers[MAX_NUM_SLAVES] = {0xFF, 0xFF, 0xFF};
|
|
u8 handshake;
|
|
u8 sendMask;
|
|
u8 attempt_counter;
|
|
const u8 palette = 0x81;
|
|
enum MULTIBOOT_MODES mb_mode = MODE32_NORMAL;
|
|
MultiBootParam mp;
|
|
|
|
if(!is_normal)
|
|
mb_mode = MODE16_MULTI;
|
|
|
|
if(is_normal)
|
|
init_sio_normal(SIO_MASTER, SIO_32);
|
|
else
|
|
init_sio_multi(SIO_MASTER);
|
|
|
|
print_multiboot_mid_process(0);
|
|
prepare_flush();
|
|
|
|
for(attempts = 0; attempts < 128; attempts++) {
|
|
for(sends = 0; sends < 16; sends++) {
|
|
multiboot_send(0x6200, is_normal, response);
|
|
|
|
for(int i = 0; i < MAX_NUM_SLAVES; i++)
|
|
if((response[i] & 0xFFF0) == 0x7200) {
|
|
clientMask |= response[i];
|
|
}
|
|
}
|
|
|
|
if(clientMask)
|
|
break;
|
|
else
|
|
VBlankIntrWait();
|
|
}
|
|
|
|
if(!clientMask) {
|
|
return MB_NO_INIT_SYNC;
|
|
}
|
|
|
|
clientMask &= 0xF;
|
|
multiboot_send(0x6100 | clientMask, is_normal, response);
|
|
for(int i = 0; i < MAX_NUM_SLAVES; i++) {
|
|
client_bit = 1 << (i + 1);
|
|
|
|
if ((clientMask & client_bit) && (response[i] != (0x7200 | client_bit)))
|
|
return MB_WRONG_ANSWER;
|
|
}
|
|
|
|
for(halves = 0; halves < 0x60; ++halves) {
|
|
multiboot_send(*data++, is_normal, response);
|
|
for(int i = 0; i < MAX_NUM_SLAVES; i++) {
|
|
client_bit = 1 << (i + 1);
|
|
|
|
if ((clientMask & client_bit) && (response[i] != (((0x60 - halves) << 8) | client_bit)))
|
|
return MB_HEADER_ISSUE;
|
|
}
|
|
}
|
|
|
|
multiboot_send(0x6200, is_normal, response);
|
|
for(int i = 0; i < MAX_NUM_SLAVES; i++) {
|
|
client_bit = 1 << (i + 1);
|
|
|
|
if ((clientMask & client_bit) && (response[i] != client_bit))
|
|
return MB_WRONG_ANSWER;
|
|
}
|
|
|
|
multiboot_send(0x6200 | clientMask, is_normal, response);
|
|
for(int i = 0; i < MAX_NUM_SLAVES; i++) {
|
|
client_bit = 1 << (i + 1);
|
|
|
|
if ((clientMask & client_bit) && (response[i] != (0x7200 | client_bit)))
|
|
return MB_WRONG_ANSWER;
|
|
}
|
|
|
|
sendMask = clientMask;
|
|
attempt_counter = 0;
|
|
|
|
while(sendMask) {
|
|
multiboot_send(0x6300 | palette, is_normal, response);
|
|
|
|
for(int i = 0; i < MAX_NUM_SLAVES; i++) {
|
|
client_bit = 1 << (i + 1);
|
|
|
|
if ((clientMask & client_bit) && ((response[i] & 0xFF00) == 0x7300)) {
|
|
answers[i] = response[i] & 0xFF;
|
|
sendMask &= ~client_bit;
|
|
}
|
|
}
|
|
attempt_counter++;
|
|
|
|
if((attempt_counter == MAX_PALETTE_ATTEMPTS) && sendMask)
|
|
return MB_PALETTE_FAILURE;
|
|
}
|
|
|
|
handshake = 0x11;
|
|
for(int i = 0; i < MAX_NUM_SLAVES; i++)
|
|
handshake += answers[i];
|
|
|
|
multiboot_send(0x6400 | handshake, is_normal, response);
|
|
for(int i = 0; i < MAX_NUM_SLAVES; i++) {
|
|
client_bit = 1 << (i + 1);
|
|
|
|
if ((clientMask & client_bit) && ((response[i] & 0xFF00) != 0x7300))
|
|
return MB_WRONG_ANSWER;
|
|
}
|
|
|
|
print_multiboot_mid_process(1);
|
|
prepare_flush();
|
|
VBlankIntrWait();
|
|
|
|
mp.handshake_data = handshake;
|
|
for(int i = 0; i < MAX_NUM_SLAVES; i++)
|
|
mp.client_data[i] = answers[i];
|
|
mp.palette_data = palette;
|
|
mp.client_bit = clientMask;
|
|
mp.boot_srcp = (u8*)data;
|
|
mp.boot_endp = (u8*)end;
|
|
|
|
if(MultiBoot(&mp, mb_mode))
|
|
return MB_SWI_FAILURE;
|
|
|
|
#endif
|
|
return MB_SUCCESS;
|
|
}
|