| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363 |
- //
- // Copyright 2020 Electronic Arts Inc.
- //
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
- // software: you can redistribute it and/or modify it under the terms of
- // the GNU General Public License as published by the Free Software Foundation,
- // either version 3 of the License, or (at your option) any later version.
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
- // in the hope that it will be useful, but with permitted additional restrictions
- // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
- // distributed with this program. You should have received a copy of the
- // GNU General Public License along with permitted additional restrictions
- // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
- #include "mpmgrd.h"
- extern "C" {
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <assert.h>
- #include "types.h"
- #include "rtq.h"
- #include "services.h"
- }
- #include "mplib.h"
- #include "mplpc.h"
- #define STATUS_OK 1
- #define STATUS_BAD 0
- #define BROADCAST_ADDR 0
- typedef struct {
- DWORD address;
- char Data[1];
- } packet;
- #define min(a,b) (((a) < (b)) ? (a) : (b))
- #define FREEQUEUE 0
- #define DOSWORKQUEUE 1
- #define WINWORKQUEUE 2
- #define WINSENDQUEUE 3
- #define DOSPENDINGQUEUE 4
- #define WINWORKQUEUE2 5
- // 6, 7, 8, taken up by LPC services
- #define GDOSWORKQUEUE 14
- #define GWINWORKQUEUE 15
- #define GWINSENDQUEUE 16
- #define GDOSPENDINGQUEUE 17
- #define GWINWORKQUEUE2 18
- MPlayerManClass::MPlayerManClass(void) : ConnManClass()
- {
- unsigned size;
- MGenGetMasterNode(&size);
- if (size != sizeof(RTQ_NODE)) {
- exit(-234);
- }
- _myAddr = LPCGetMPAddr();
- _nConnections = 0;
- for (int i = 0; i < CONNECT_MAX; i++) {
- _Connections[i] = 0;
- strcpy(_Names[i], "");
- }
- }
- // here's what we do to get private & broadcasts over the same chunnel
- // we package up an extra dword at the beginning to indicate the address
- int
- MPlayerManClass::Send_Private_Message(void *buf,
- int buflen,
- int /* ack_req */,
- int conn_id)
- {
- RTQ_NODE *n;
- int idx = Connection_Index(conn_id);
- if (_nConnections == 0) {
- return (STATUS_OK);
- }
- while ((n = MGenMoveTo(FREEQUEUE, DOSWORKQUEUE)) == 0);
- packet *p = (packet *) n->rtqDatum;
- if (conn_id == CONNECTION_NONE) {
- p->address = BROADCAST_ADDR;
- } else {
- p->address = _Connections[idx];
- }
- memcpy(p->Data, buf, buflen);
- n->rtqUpCtr = (WORD)(buflen + sizeof(DWORD));
- MGenMoveTo(DOSWORKQUEUE, WINSENDQUEUE);
- PostWindowsMessage();
- Yield();
- return STATUS_OK;
- }
- int
- MPlayerManClass::Get_Private_Message(void *buf, int *buflen,
- int *conn_id)
- {
- RTQ_NODE *n;
- int i;
- if ((n = MGenMoveTo(DOSPENDINGQUEUE, DOSWORKQUEUE)) == 0) {
- *buflen = 0;
- return 0;
- }
- packet *p = (packet *) n->rtqDatum;
- int lentocpy = n->rtqUpCtr - sizeof(DWORD);
- *conn_id = CONNECTION_NONE;
- for (i = 0; i < _nConnections; i++) {
- if (p->address == _Connections[i]) {
- (*conn_id) = _ID[i];
- break;
- }
- }
- memcpy(buf, p->Data, lentocpy);
- *buflen = lentocpy;
- MGenMoveTo(DOSWORKQUEUE, FREEQUEUE);
- return STATUS_OK;
- }
- int
- MPlayerManClass::Send_Global_Message(void *buf, int buflen, int /*ack_req*/,
- int address)
- {
- RTQ_NODE *n;
- while ((n = MGenMoveTo(FREEQUEUE, DOSWORKQUEUE)) == 0);
- packet *p = (packet *) n->rtqDatum;
- if (address == 0) {
- p->address = BROADCAST_ADDR;
- } else {
- p->address = address;
- }
- memcpy(p->Data, buf, buflen);
- n->rtqUpCtr = (WORD)(buflen + sizeof(DWORD));
- MGenMoveTo(DOSWORKQUEUE, GWINSENDQUEUE);
- PostWindowsMessage();
- Yield();
- return STATUS_OK;
- }
- int
- MPlayerManClass::Get_Global_Message(void *buf, int *buflen, int *address)
- {
- RTQ_NODE *n;
- if ((n = MGenMoveTo(GDOSPENDINGQUEUE, DOSWORKQUEUE)) == 0) {
- *buflen = 0;
- return 0;
- }
- packet *p = (packet *) n->rtqDatum;
- int lentocpy = n->rtqUpCtr - sizeof(DWORD);
- if (address) {
- if (p->address == BROADCAST_ADDR) {
- *address = 0;
- } else {
- *address = p->address;
- }
- }
- memcpy(buf, p->Data, lentocpy);
- *buflen = lentocpy;
- MGenMoveTo(DOSWORKQUEUE, FREEQUEUE);
- return STATUS_OK;
- }
- int
- MPlayerManClass::Service(void)
- {
- return STATUS_OK;
- }
- int
- MPlayerManClass::Create_Connection(int id, char *name, int address)
- {
- _Connections[_nConnections] = address;
- _ID[_nConnections] = id;
- strcpy(_Names[_nConnections], name);
- _nConnections++;
- return STATUS_OK;
- }
- int
- MPlayerManClass::Delete_Connection(int id)
- {
- int i;
- int idx = Connection_Index(id);
- if (idx == -1)
- return 0;
- for (i = idx; i < _nConnections - 1; i++) {
- _Connections[i] = _Connections[i+1];
- _ID[i] = _ID[i+1];
- strcpy (_Names[i], _Names[i+1]);
- }
- _nConnections--;
- return STATUS_OK;
- }
- char *
- MPlayerManClass::Connection_Name(int id)
- {
- int idx = Connection_Index(id);
- if (idx==-1) {
- return (NULL);
- }
- return _Names[idx];
- }
- int
- MPlayerManClass::Connection_Address(int id)
- {
- int idx = Connection_Index(id);
- if (idx==-1) {
- return (0);
- }
- return _Connections[idx];
- }
- int
- MPlayerManClass::Num_Connections(void)
- {
- return _nConnections;
- }
- int
- MPlayerManClass::Connection_ID(int index)
- {
- return _ID[index];
- }
- int
- MPlayerManClass::Connection_Index(int id)
- {
- int i;
- for (i = 0; i < _nConnections; i++) {
- if (_ID[i] == id) {
- return i;
- }
- }
- return -1;
- }
- int
- MPlayerManClass::Global_Num_Send(void)
- {
- return 0;
- }
- int
- MPlayerManClass::Global_Num_Receive(void)
- {
- return MGenGetQueueCtr(GDOSPENDINGQUEUE);
- }
- int
- MPlayerManClass::Private_Num_Send(int /*id*/)
- {
- return 0;
- }
- int
- MPlayerManClass::Private_Num_Receive(int /*id*/)
- {
- return MGenGetQueueCtr(DOSPENDINGQUEUE);
- }
- void
- MPlayerManClass::Reset_Response_Time(void)
- {
- // unsupported
- }
- unsigned long
- MPlayerManClass::Response_Time(void)
- {
- return (160 * 60) / 1000; // 160 microseconds one way (9 ticks)
- }
- void
- MPlayerManClass::Set_Timing(unsigned long /*retrydelta*/,
- unsigned long /*maxretries*/,
- unsigned long /*timeout*/)
- {
- // unsupported
- }
- void
- MPlayerManClass::Configure_Debug(int /*index*/, int /*type_offset*/,
- int /*type_size*/, char ** /*names*/,
- int /*namestart*/, int /*namecount*/)
- {
- // unsupported
- }
- void
- MPlayerManClass::Mono_Debug_Print(int /*index*/, int /*refresh*/)
- {
- // unsupported
- }
- int
- MPlayerManClass::Init(void)
- {
- return STATUS_OK;
- }
- int MPlayerManClass::Find_Num_Connections(void)
- {
- TGAMEDEF game_def;
- int sz = sizeof(game_def);
- GetGameDef(&game_def, &sz);
- return (game_def.numPlayers - 1);
- }
- void MPlayerManClass::Flush_All(void)
- {
- MGenFlushNodes(DOSPENDINGQUEUE, FREEQUEUE);
- MGenFlushNodes(GDOSPENDINGQUEUE, FREEQUEUE);
- }
|