move maple definitions to a new maple/ directory
maple.cpp now uses the new maple_bus_commands.h
This commit is contained in:
parent
c8ed8cdf9e
commit
481a0cb0dc
31
1bpp.py
Normal file
31
1bpp.py
Normal file
@ -0,0 +1,31 @@
|
||||
import sys
|
||||
|
||||
width = 640
|
||||
height = 480
|
||||
|
||||
with open(sys.argv[1], 'rb') as f:
|
||||
b = f.read()
|
||||
assert len(b) == width * height, len(b)
|
||||
|
||||
buf = []
|
||||
|
||||
for i in range(len(b) // 8):
|
||||
ix = i * 8
|
||||
px = b[ix:ix + 8]
|
||||
assert all(p in {0, 1} for p in px)
|
||||
out = (
|
||||
(px[0] << 7)
|
||||
| (px[1] << 6)
|
||||
| (px[2] << 5)
|
||||
| (px[3] << 4)
|
||||
| (px[4] << 3)
|
||||
| (px[5] << 2)
|
||||
| (px[6] << 1)
|
||||
| (px[7] << 0)
|
||||
)
|
||||
buf.append(out)
|
||||
|
||||
assert len(buf) == width * height // 8
|
||||
|
||||
with open(sys.argv[2], 'wb') as f:
|
||||
f.write(bytes(buf))
|
2
Makefile
2
Makefile
@ -13,7 +13,7 @@ MAIN_OBJ = \
|
||||
holly/region_array.o \
|
||||
holly/ta_fifo_polygon_converter.o \
|
||||
holly/core.o \
|
||||
maple.o \
|
||||
maple/maple.o \
|
||||
scene.o \
|
||||
macaw.data.o \
|
||||
$(LIBGCC)
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "float_uint32.h"
|
||||
#include "../float_uint32.h"
|
||||
#include "core_bits.h"
|
||||
#include "../holly.h"
|
||||
#include "../memorymap.h"
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include <cstdint>
|
||||
|
||||
#include "float_uint32.h"
|
||||
#include "../float_uint32.h"
|
||||
|
||||
namespace id {
|
||||
constexpr uint32_t device_id(uint32_t reg) { return (reg >> 16) & 0xffff; }
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include <cstdint>
|
||||
|
||||
#include "float_uint32.h"
|
||||
#include "../float_uint32.h"
|
||||
|
||||
namespace ta_ol_base {
|
||||
constexpr uint32_t base_address(uint32_t num) { return (num & 0xffffe0) << 0; }
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
#include "float_uint32.h"
|
||||
#include "../float_uint32.h"
|
||||
#include "isp_tsp.h"
|
||||
|
||||
namespace para_control {
|
||||
|
4
main.cpp
4
main.cpp
@ -9,8 +9,8 @@
|
||||
#include "holly/core_bits.h"
|
||||
#include "holly/ta_fifo_polygon_converter.h"
|
||||
#include "systembus.h"
|
||||
#include "maple.h"
|
||||
#include "maple_bits.h"
|
||||
#include "maple/maple.h"
|
||||
#include "maple/maple_bits.h"
|
||||
|
||||
#include "holly/texture_memory_alloc.h"
|
||||
|
||||
|
@ -1,12 +1,13 @@
|
||||
#include <cstdint>
|
||||
#include <bit>
|
||||
|
||||
#include "sh7091.h"
|
||||
#include "sh7091_bits.h"
|
||||
#include "systembus.h"
|
||||
#include "systembus_bits.h"
|
||||
#include "maple_bits.h"
|
||||
#include "../sh7091.h"
|
||||
#include "../sh7091_bits.h"
|
||||
#include "../systembus.h"
|
||||
#include "../systembus_bits.h"
|
||||
|
||||
#include "maple_bits.h"
|
||||
#include "maple_bus_commands.h"
|
||||
#include "maple.h"
|
||||
|
||||
#define AP__PO__A (0b00 << 6)
|
||||
@ -30,32 +31,31 @@
|
||||
#define HOST_INSTRUCTION__PORT_SELECT__D (0b11 << 16)
|
||||
#define HOST_INSTRUCTION__TRANSFER_LENGTH(n) (((n) & 0xff) << 0)
|
||||
|
||||
template <int N>
|
||||
template <typename T>
|
||||
struct maple_host_command {
|
||||
uint32_t host_instruction;
|
||||
uint32_t receive_data_storage_address;
|
||||
uint32_t protocol_data[N];
|
||||
uint8_t command_code;
|
||||
uint8_t destination_ap;
|
||||
uint8_t source_ap;
|
||||
uint8_t data_size;
|
||||
T data_fields;
|
||||
};
|
||||
|
||||
void maple_init_host_command(uint32_t * buf, uint32_t * receive_address)
|
||||
{
|
||||
auto command = reinterpret_cast<maple_host_command<1> *>(buf);
|
||||
auto host_command = reinterpret_cast<maple_host_command<device_request::data_fields> *>(buf);
|
||||
|
||||
command->host_instruction = HOST_INSTRUCTION__END_FLAG
|
||||
| HOST_INSTRUCTION__PORT_SELECT__A
|
||||
| HOST_INSTRUCTION__TRANSFER_LENGTH(0); // 4 bytes
|
||||
host_command->host_instruction = HOST_INSTRUCTION__END_FLAG
|
||||
| HOST_INSTRUCTION__PORT_SELECT__A
|
||||
| HOST_INSTRUCTION__TRANSFER_LENGTH(0); // 4 bytes
|
||||
|
||||
command->receive_data_storage_address = reinterpret_cast<uint32_t>(receive_address);
|
||||
host_command->receive_data_storage_address = reinterpret_cast<uint32_t>(receive_address);
|
||||
|
||||
uint32_t command_code = 0x01; // 'Device Request'
|
||||
uint32_t destination_ap = AP__DE__DEVICE | AP__PO__A;
|
||||
uint32_t source_ap = AP__PO__A;
|
||||
uint32_t data_size = 0;
|
||||
// maple bus is big endian
|
||||
command->protocol_data[0] = std::byteswap( (command_code << 24)
|
||||
| (destination_ap << 16)
|
||||
| (source_ap << 8)
|
||||
| (data_size << 0));
|
||||
host_command->command_code = device_request::command_code;
|
||||
host_command->destination_ap = AP__DE__DEVICE | AP__PO__A;
|
||||
host_command->source_ap = AP__PO__A;
|
||||
host_command->data_size = 0;
|
||||
}
|
||||
|
||||
void maple_dma_start(uint32_t * command_buf)
|
@ -1,6 +1,6 @@
|
||||
#include <cstdint>
|
||||
|
||||
#include "holly/float_uint32.h"
|
||||
#include "../float_uint32.h"
|
||||
|
||||
namespace mdstar {
|
||||
constexpr uint32_t table_address(uint32_t num) { return (num & 0xfffffe0) << 0; }
|
||||
@ -31,12 +31,12 @@ namespace mdst {
|
||||
namespace msys {
|
||||
constexpr uint32_t time_out_counter(uint32_t num) { return (num & 0xffff) << 16; }
|
||||
constexpr uint32_t single_hard_trigger = 1 << 12;
|
||||
|
||||
|
||||
namespace sending_rate {
|
||||
constexpr uint32_t _2M = 0 << 8;
|
||||
constexpr uint32_t _1M = 1 << 8;
|
||||
}
|
||||
|
||||
|
||||
constexpr uint32_t delay_time(uint32_t num) { return (num & 0xf) << 0; }
|
||||
}
|
||||
|
||||
@ -75,4 +75,3 @@ namespace mrxdad {
|
||||
namespace mrxdbd {
|
||||
constexpr uint32_t rxd_base_address(uint32_t reg) { return (reg >> 0) & 0x1fffffff; }
|
||||
}
|
||||
|
231
maple/maple_bus_commands.h
Normal file
231
maple/maple_bus_commands.h
Normal file
@ -0,0 +1,231 @@
|
||||
#include <cstdint>
|
||||
|
||||
namespace device_request {
|
||||
constexpr uint32_t command_code = 0x1;
|
||||
|
||||
struct data_fields {
|
||||
};
|
||||
}
|
||||
|
||||
namespace all_status_request {
|
||||
constexpr uint32_t command_code = 0x2;
|
||||
|
||||
struct data_fields {
|
||||
};
|
||||
}
|
||||
|
||||
namespace device_reset {
|
||||
constexpr uint32_t command_code = 0x3;
|
||||
|
||||
struct data_fields {
|
||||
};
|
||||
}
|
||||
|
||||
namespace device_kill {
|
||||
constexpr uint32_t command_code = 0x4;
|
||||
|
||||
struct data_fields {
|
||||
};
|
||||
}
|
||||
|
||||
namespace device_status {
|
||||
constexpr uint32_t command_code = 0x5;
|
||||
|
||||
struct data_fields {
|
||||
uint8_t device_id[16];
|
||||
uint8_t destination_code[1];
|
||||
uint8_t connection_direction[1];
|
||||
uint8_t product_name[30];
|
||||
uint8_t license[60];
|
||||
uint8_t low_consumption_standby_current[2];
|
||||
uint8_t maximum_current_consumption[2];
|
||||
};
|
||||
|
||||
static_assert((sizeof (struct data_fields)) == 112);
|
||||
}
|
||||
|
||||
namespace device_all_status {
|
||||
constexpr uint32_t command_code = 0x6;
|
||||
|
||||
template <int N>
|
||||
struct data_fields {
|
||||
uint8_t device_id[16];
|
||||
uint8_t destination_code[1];
|
||||
uint8_t connection_direction[1];
|
||||
uint8_t product_name[30];
|
||||
uint8_t license[60];
|
||||
uint8_t low_consumption_standby_current[2];
|
||||
uint8_t maximum_current_consumption[2];
|
||||
uint8_t free_device_status[N];
|
||||
};
|
||||
|
||||
static_assert((sizeof (struct data_fields<0>)) == 112);
|
||||
}
|
||||
|
||||
namespace device_reply {
|
||||
constexpr uint32_t command_code = 0x7;
|
||||
|
||||
struct data_fields {
|
||||
};
|
||||
}
|
||||
|
||||
namespace data_transfer {
|
||||
constexpr uint32_t command_code = 0x8;
|
||||
|
||||
template <int N>
|
||||
struct data_fields {
|
||||
uint8_t data[N];
|
||||
};
|
||||
|
||||
static_assert((sizeof (struct data_fields<0>)) == 0);
|
||||
}
|
||||
|
||||
namespace get_condition {
|
||||
constexpr uint32_t command_code = 0x9;
|
||||
|
||||
struct data_fields {
|
||||
uint8_t function_type[4];
|
||||
};
|
||||
|
||||
static_assert((sizeof (struct data_fields)) == 4);
|
||||
}
|
||||
|
||||
namespace get_media_info {
|
||||
constexpr uint32_t command_code = 0xa;
|
||||
|
||||
struct data_fields {
|
||||
uint8_t function_type[4];
|
||||
uint8_t pt[4];
|
||||
};
|
||||
|
||||
static_assert((sizeof (struct data_fields)) == 8);
|
||||
}
|
||||
|
||||
namespace block_read {
|
||||
constexpr uint32_t command_code = 0xb;
|
||||
|
||||
struct data_fields {
|
||||
uint8_t function_type[4];
|
||||
uint8_t pt[1];
|
||||
uint8_t phase[1];
|
||||
uint8_t block_no[2];
|
||||
};
|
||||
|
||||
static_assert((sizeof (struct data_fields)) == 8);
|
||||
}
|
||||
|
||||
namespace block_write {
|
||||
constexpr uint32_t command_code = 0xc;
|
||||
|
||||
template <int N>
|
||||
struct data_fields {
|
||||
uint8_t function_type[4];
|
||||
uint8_t pt[1];
|
||||
uint8_t phase[1];
|
||||
uint8_t block_no[2];
|
||||
uint8_t written_data[N];
|
||||
};
|
||||
|
||||
static_assert((sizeof (struct data_fields<0>)) == 8);
|
||||
}
|
||||
|
||||
namespace get_last_error {
|
||||
constexpr uint32_t command_code = 0xd;
|
||||
|
||||
struct data_fields {
|
||||
uint8_t function_type[4];
|
||||
uint8_t pt[1];
|
||||
uint8_t phase[1];
|
||||
uint8_t block_no[2];
|
||||
};
|
||||
|
||||
static_assert((sizeof (struct data_fields)) == 8);
|
||||
}
|
||||
|
||||
namespace set_condition {
|
||||
constexpr uint32_t command_code = 0xe;
|
||||
|
||||
template <int N>
|
||||
struct data_fields {
|
||||
uint8_t function_type[4];
|
||||
uint8_t write_in_data[N];
|
||||
};
|
||||
|
||||
static_assert((sizeof (struct data_fields<0>)) == 4);
|
||||
}
|
||||
|
||||
namespace ft4_control {
|
||||
constexpr uint32_t command_code = 0xf;
|
||||
|
||||
template <int N>
|
||||
struct data_fields {
|
||||
uint8_t function_type[4];
|
||||
uint8_t ft4_data[N];
|
||||
};
|
||||
|
||||
static_assert((sizeof (struct data_fields<0>)) == 4);
|
||||
}
|
||||
|
||||
namespace ar_control {
|
||||
constexpr uint32_t command_code = 0x10;
|
||||
|
||||
template <int N>
|
||||
struct data_fields {
|
||||
uint8_t function_type[4];
|
||||
uint8_t data[N];
|
||||
};
|
||||
|
||||
static_assert((sizeof (struct data_fields<0>)) == 4);
|
||||
}
|
||||
|
||||
namespace function_type_unknown {
|
||||
constexpr uint32_t command_code = 0xfe;
|
||||
|
||||
struct data_fields {
|
||||
};
|
||||
}
|
||||
|
||||
namespace command_unknown {
|
||||
constexpr uint32_t command_code = 0xfd;
|
||||
|
||||
struct data_fields {
|
||||
};
|
||||
}
|
||||
|
||||
namespace transmit_again {
|
||||
constexpr uint32_t command_code = 0xfc;
|
||||
|
||||
struct data_fields {
|
||||
};
|
||||
}
|
||||
|
||||
namespace file_error {
|
||||
constexpr uint32_t command_code = 0xfb;
|
||||
|
||||
struct data_fields {
|
||||
uint8_t function_error_code[4];
|
||||
};
|
||||
|
||||
static_assert((sizeof (struct data_fields)) == 4);
|
||||
}
|
||||
|
||||
namespace lcd_error {
|
||||
constexpr uint32_t command_code = 0xfa;
|
||||
|
||||
struct data_fields {
|
||||
uint8_t function_error_code[4];
|
||||
};
|
||||
|
||||
static_assert((sizeof (struct data_fields)) == 4);
|
||||
}
|
||||
|
||||
namespace ar_error {
|
||||
constexpr uint32_t command_code = 0xf9;
|
||||
|
||||
struct data_fields {
|
||||
uint8_t function_error_code[4];
|
||||
};
|
||||
|
||||
static_assert((sizeof (struct data_fields)) == 4);
|
||||
}
|
||||
|
@ -5,24 +5,32 @@
|
||||
|
||||
namespace device_request {
|
||||
constexpr uint32_t command_code = 0x1;
|
||||
struct data_fields {
|
||||
};
|
||||
}
|
||||
|
||||
namespace all_status_request {
|
||||
constexpr uint32_t command_code = 0x2;
|
||||
struct data_fields {
|
||||
};
|
||||
}
|
||||
|
||||
namespace device_reset {
|
||||
constexpr uint32_t command_code = 0x3;
|
||||
struct data_fields {
|
||||
};
|
||||
}
|
||||
|
||||
namespace device_kill {
|
||||
constexpr uint32_t command_code = 0x4;
|
||||
struct data_fields {
|
||||
};
|
||||
}
|
||||
|
||||
namespace device_status {
|
||||
constexpr uint32_t command_code = 0x5;
|
||||
|
||||
struct data_fields {
|
||||
|
||||
uint8_t device_id[16];
|
||||
uint8_t destination_code[1];
|
||||
uint8_t connection_direction[1];
|
||||
@ -31,15 +39,15 @@ namespace device_status {
|
||||
uint8_t low_consumption_standby_current[2];
|
||||
uint8_t maximum_current_consumption[2];
|
||||
};
|
||||
|
||||
|
||||
static_assert((sizeof (struct data_fields)) == 112);
|
||||
}
|
||||
|
||||
namespace device_all_status {
|
||||
constexpr uint32_t command_code = 0x6;
|
||||
|
||||
template <int N>
|
||||
struct data_fields {
|
||||
|
||||
template <int N>
|
||||
uint8_t device_id[16];
|
||||
uint8_t destination_code[1];
|
||||
uint8_t connection_direction[1];
|
||||
@ -49,162 +57,169 @@ namespace device_all_status {
|
||||
uint8_t maximum_current_consumption[2];
|
||||
uint8_t free_device_status[N];
|
||||
};
|
||||
|
||||
|
||||
static_assert((sizeof (struct data_fields<0>)) == 112);
|
||||
}
|
||||
|
||||
namespace device_reply {
|
||||
constexpr uint32_t command_code = 0x7;
|
||||
struct data_fields {
|
||||
};
|
||||
}
|
||||
|
||||
namespace data_transfer {
|
||||
constexpr uint32_t command_code = 0x8;
|
||||
|
||||
template <int N>
|
||||
struct data_fields {
|
||||
|
||||
template <int N>
|
||||
uint8_t data[N];
|
||||
};
|
||||
|
||||
|
||||
static_assert((sizeof (struct data_fields<0>)) == 0);
|
||||
}
|
||||
|
||||
namespace get_condition {
|
||||
constexpr uint32_t command_code = 0x9;
|
||||
|
||||
struct data_fields {
|
||||
|
||||
uint8_t function_type[4];
|
||||
};
|
||||
|
||||
|
||||
static_assert((sizeof (struct data_fields)) == 4);
|
||||
}
|
||||
|
||||
namespace get_media_info {
|
||||
constexpr uint32_t command_code = 0xa;
|
||||
|
||||
struct data_fields {
|
||||
|
||||
uint8_t function_type[4];
|
||||
uint8_t pt[4];
|
||||
};
|
||||
|
||||
|
||||
static_assert((sizeof (struct data_fields)) == 8);
|
||||
}
|
||||
|
||||
namespace block_read {
|
||||
constexpr uint32_t command_code = 0xb;
|
||||
|
||||
struct data_fields {
|
||||
|
||||
uint8_t function_type[4];
|
||||
uint8_t pt[1];
|
||||
uint8_t phase[1];
|
||||
uint8_t block_no[2];
|
||||
};
|
||||
|
||||
|
||||
static_assert((sizeof (struct data_fields)) == 8);
|
||||
}
|
||||
|
||||
namespace block_write {
|
||||
constexpr uint32_t command_code = 0xc;
|
||||
|
||||
template <int N>
|
||||
struct data_fields {
|
||||
|
||||
template <int N>
|
||||
uint8_t function_type[4];
|
||||
uint8_t pt[1];
|
||||
uint8_t phase[1];
|
||||
uint8_t block_no[2];
|
||||
uint8_t written_data[N];
|
||||
};
|
||||
|
||||
|
||||
static_assert((sizeof (struct data_fields<0>)) == 8);
|
||||
}
|
||||
|
||||
namespace get_last_error {
|
||||
constexpr uint32_t command_code = 0xd;
|
||||
|
||||
struct data_fields {
|
||||
|
||||
uint8_t function_type[4];
|
||||
uint8_t pt[1];
|
||||
uint8_t phase[1];
|
||||
uint8_t block_no[2];
|
||||
};
|
||||
|
||||
|
||||
static_assert((sizeof (struct data_fields)) == 8);
|
||||
}
|
||||
|
||||
namespace set_condition {
|
||||
constexpr uint32_t command_code = 0xe;
|
||||
|
||||
template <int N>
|
||||
struct data_fields {
|
||||
|
||||
template <int N>
|
||||
uint8_t function_type[4];
|
||||
uint8_t write_in_data[N];
|
||||
};
|
||||
|
||||
|
||||
static_assert((sizeof (struct data_fields<0>)) == 4);
|
||||
}
|
||||
|
||||
namespace ft4_control {
|
||||
constexpr uint32_t command_code = 0xf;
|
||||
|
||||
template <int N>
|
||||
struct data_fields {
|
||||
|
||||
template <int N>
|
||||
uint8_t function_type[4];
|
||||
uint8_t ft4_data[N];
|
||||
};
|
||||
|
||||
|
||||
static_assert((sizeof (struct data_fields<0>)) == 4);
|
||||
}
|
||||
|
||||
namespace ar_control {
|
||||
constexpr uint32_t command_code = 0x10;
|
||||
|
||||
template <int N>
|
||||
struct data_fields {
|
||||
|
||||
template <int N>
|
||||
uint8_t function_type[4];
|
||||
uint8_t data[N];
|
||||
};
|
||||
|
||||
|
||||
static_assert((sizeof (struct data_fields<0>)) == 4);
|
||||
}
|
||||
|
||||
namespace function_type_unknown {
|
||||
constexpr uint32_t command_code = 0xfe;
|
||||
struct data_fields {
|
||||
};
|
||||
}
|
||||
|
||||
namespace command_unknown {
|
||||
constexpr uint32_t command_code = 0xfd;
|
||||
struct data_fields {
|
||||
};
|
||||
}
|
||||
|
||||
namespace transmit_again {
|
||||
constexpr uint32_t command_code = 0xfc;
|
||||
struct data_fields {
|
||||
};
|
||||
}
|
||||
|
||||
namespace file_error {
|
||||
constexpr uint32_t command_code = 0xfb;
|
||||
|
||||
struct data_fields {
|
||||
|
||||
uint8_t function_error_code[4];
|
||||
};
|
||||
|
||||
|
||||
static_assert((sizeof (struct data_fields)) == 4);
|
||||
}
|
||||
|
||||
namespace lcd_error {
|
||||
constexpr uint32_t command_code = 0xfa;
|
||||
|
||||
struct data_fields {
|
||||
|
||||
uint8_t function_error_code[4];
|
||||
};
|
||||
|
||||
|
||||
static_assert((sizeof (struct data_fields)) == 4);
|
||||
}
|
||||
|
||||
namespace ar_error {
|
||||
constexpr uint32_t command_code = 0xf9;
|
||||
|
||||
struct data_fields {
|
||||
|
||||
uint8_t function_error_code[4];
|
||||
};
|
||||
|
||||
|
||||
static_assert((sizeof (struct data_fields)) == 4);
|
||||
}
|
||||
|
||||
|
11
notes/hamming-framing.txt
Normal file
11
notes/hamming-framing.txt
Normal file
@ -0,0 +1,11 @@
|
||||
frames:
|
||||
0b00 invalid
|
||||
0b01 command begin
|
||||
0b10 data begin
|
||||
0b11 frame end
|
||||
|
||||
commands:
|
||||
- jump addr
|
||||
- read addr
|
||||
- write addr
|
||||
- speed value
|
@ -206,7 +206,7 @@ def render_registers(registers):
|
||||
def header():
|
||||
yield "#include <cstdint>"
|
||||
yield ""
|
||||
yield '#include "float_uint32.h"'
|
||||
yield '#include "../float_uint32.h"'
|
||||
yield ""
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -3,7 +3,6 @@ from typing import Union
|
||||
import sys
|
||||
|
||||
from sh7091 import read_input
|
||||
from sh7091 import headers
|
||||
from generate import renderer
|
||||
|
||||
@dataclass
|
||||
@ -17,15 +16,15 @@ def command_namespace(namespace: CommandNamespace,
|
||||
data_fields: list[tuple[str, tuple[int, str]]]):
|
||||
yield f"namespace {namespace.name} {{"
|
||||
yield f"constexpr uint32_t command_code = {hex(namespace.command_code)};"
|
||||
yield ""
|
||||
|
||||
if namespace.data_size == (0, None):
|
||||
assert data_fields == []
|
||||
# do nothing
|
||||
yield "struct data_fields {"
|
||||
yield "};"
|
||||
else:
|
||||
length, variable = namespace.data_size
|
||||
|
||||
yield ""
|
||||
|
||||
if variable is not None:
|
||||
assert variable.lower() == "n"
|
||||
yield "template <int N>"
|
||||
@ -149,6 +148,10 @@ def new_aggregator():
|
||||
|
||||
return process
|
||||
|
||||
def headers():
|
||||
yield "#include <cstdint>"
|
||||
yield ""
|
||||
|
||||
input_file = sys.argv[1]
|
||||
rows = read_input(input_file)
|
||||
process = new_aggregator()
|
||||
|
Loading…
x
Reference in New Issue
Block a user