Merge pull request #1009 from zsilencer/develop

Decompile 6CB7FB, 6B49D9, 6C0BB5, 6C09D1, 6C0B83
This commit is contained in:
Ted John 2015-04-28 15:07:09 +01:00
commit 54cf1c4371
38 changed files with 1831 additions and 303 deletions

View File

@ -1427,13 +1427,8 @@ int sound_play_panned(int sound_id, int ebx, sint16 x, sint16 y, sint16 z)
RCT2_GLOBAL(0x00F438AD, uint8) = 0;
int volume = 0;
if (ebx == 0x8001) {
sint16 x2 = x & 0xFFE0; // round by 32
sint16 y2 = y & 0xFFE0;
if (x2 < 0x1FFF && y2 < 0x1FFF) {
rct_map_element* mapelement = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[((y2 * 256 + x2) & 0xFFFF) / 8];
while (map_element_get_type(mapelement) != MAP_ELEMENT_TYPE_SURFACE) {
mapelement++;
}
rct_map_element* mapelement = map_get_surface_element_at(x / 32, y / 32);
if (mapelement) {
if ((mapelement->base_height * 8) - 5 > z) {
RCT2_GLOBAL(0x00F438AD, uint8) = 10;
}
@ -1560,7 +1555,7 @@ void start_title_music()
&& RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TITLE_DEMO) {
if (!RCT2_GLOBAL(0x009AF600, uint8)) {
#ifdef USE_MIXER
gTitleMusicChannel = Mixer_Play_Music(musicPathId);
gTitleMusicChannel = Mixer_Play_Music(musicPathId, true);
#else
RCT2_GLOBAL(0x014241BC, uint32) = 1;
int result = sound_channel_load_file2(3, (char*)get_file_path(musicPathId), 0);

View File

@ -31,21 +31,64 @@ extern "C" {
Mixer gMixer;
Sample::Sample()
Source::~Source()
{
}
unsigned long Source::GetSome(unsigned long offset, const uint8** data, unsigned long length)
{
if (offset >= Length()) {
return 0;
}
unsigned long size = length;
if (offset + length > Length()) {
size = Length() - offset;
}
return Read(offset, data, size);
}
unsigned long Source::Length()
{
return length;
}
const AudioFormat& Source::Format()
{
return format;
}
Source_Null::Source_Null()
{
length = 0;
}
unsigned long Source_Null::Read(unsigned long offset, const uint8** data, unsigned long length)
{
return 0;
}
Source_Sample::Source_Sample()
{
data = 0;
length = 0;
issdlwav = false;
}
Sample::~Sample()
Source_Sample::~Source_Sample()
{
Unload();
}
bool Sample::Load(const char* filename)
unsigned long Source_Sample::Read(unsigned long offset, const uint8** data, unsigned long length)
{
log_verbose("Sample::Load(%s)", filename);
*data = &Source_Sample::data[offset];
return length;
}
bool Source_Sample::LoadWAV(const char* filename)
{
log_verbose("Source_Sample::LoadWAV(%s)", filename);
utf8 utf8filename[512];
win1252_to_utf8(utf8filename, filename, sizeof(utf8filename));
@ -75,9 +118,9 @@ bool Sample::Load(const char* filename)
return true;
}
bool Sample::LoadCSS1(const char* filename, unsigned int offset)
bool Source_Sample::LoadCSS1(const char* filename, unsigned int offset)
{
log_verbose("Sample::LoadCSS1(%s, %d)", filename, offset);
log_verbose("Source_Sample::LoadCSS1(%s, %d)", filename, offset);
utf8 utf8filename[512];
win1252_to_utf8(utf8filename, filename, sizeof(utf8filename));
@ -107,13 +150,18 @@ bool Sample::LoadCSS1(const char* filename, unsigned int offset)
format.freq = waveformat.nSamplesPerSec;
format.format = AUDIO_S16LSB;
format.channels = waveformat.nChannels;
data = new uint8[length];
data = new (std::nothrow) uint8[length];
if (!data) {
log_verbose("Unable to allocate data");
SDL_RWclose(rw);
return false;
}
SDL_RWread(rw, data, length, 1);
SDL_RWclose(rw);
return true;
}
void Sample::Unload()
void Source_Sample::Unload()
{
if (data) {
if (issdlwav) {
@ -127,16 +175,11 @@ void Sample::Unload()
length = 0;
}
bool Sample::Loaded()
bool Source_Sample::Convert(AudioFormat format)
{
return data != 0;
}
bool Sample::Convert(AudioFormat format)
{
if(Sample::format.format != format.format || Sample::format.channels != format.channels || Sample::format.freq != format.freq){
if(Source_Sample::format.format != format.format || Source_Sample::format.channels != format.channels || Source_Sample::format.freq != format.freq){
SDL_AudioCVT cvt;
if (SDL_BuildAudioCVT(&cvt, Sample::format.format, Sample::format.channels, Sample::format.freq, format.format, format.channels, format.freq) < 0) {
if (SDL_BuildAudioCVT(&cvt, Source_Sample::format.format, Source_Sample::format.channels, Source_Sample::format.freq, format.format, format.channels, format.freq) < 0) {
return false;
}
cvt.len = length;
@ -149,69 +192,147 @@ bool Sample::Convert(AudioFormat format)
Unload();
data = cvt.buf;
length = cvt.len_cvt;
Sample::format = format;
Source_Sample::format = format;
return true;
}
return false;
}
const uint8* Sample::Data()
Source_SampleStream::Source_SampleStream()
{
return data;
length = 0;
rw = NULL;
buffer = 0;
buffersize = 0;
}
unsigned long Sample::Length()
Source_SampleStream::~Source_SampleStream()
{
return length;
Unload();
}
Stream::Stream()
unsigned long Source_SampleStream::Read(unsigned long offset, const uint8** data, unsigned long length)
{
sourcetype = SOURCE_NONE;
if (length > buffersize) {
if (buffer) {
delete[] buffer;
}
buffer = new (std::nothrow) uint8[length];
if (!buffer) {
return 0;
}
buffersize = length;
}
Sint64 currentposition = SDL_RWtell(rw);
if (currentposition == -1) {
return 0;
}
if (currentposition - databegin != offset) {
Sint64 newposition = SDL_RWseek(rw, databegin + offset, SEEK_SET);
if (newposition == -1) {
return 0;
}
currentposition = newposition;
}
*data = buffer;
int read = SDL_RWread(rw, buffer, 1, length);
if (read == -1) {
return 0;
}
return read;
}
unsigned long Stream::GetSome(unsigned long offset, const uint8** data, unsigned long length)
bool Source_SampleStream::LoadWAV(SDL_RWops* rw)
{
unsigned long size = length;
switch(sourcetype) {
case SOURCE_SAMPLE:
if (offset >= sample->Length()) {
return 0;
}
if (offset + length > sample->Length()) {
size = sample->Length() - offset;
}
*data = &sample->Data()[offset];
return size;
break;
Unload();
if (rw == NULL) {
return false;
}
Source_SampleStream::rw = rw;
Uint32 chunk_id = SDL_ReadLE32(rw);
const Uint32 RIFF = 0x46464952;
if (chunk_id != RIFF) {
log_verbose("Not a WAV file");
return false;
}
Uint32 chunk_size = SDL_ReadLE32(rw);
Uint32 chunk_format = SDL_ReadLE32(rw);
const Uint32 WAVE = 0x45564157;
if (chunk_format != WAVE) {
log_verbose("Not in WAVE format");
return false;
}
const Uint32 FMT = 0x20746D66;
Uint32 fmtchunk_size = FindChunk(rw, FMT);
if (!fmtchunk_size) {
log_verbose("Could not find FMT chunk");
return false;
}
PCMWAVEFORMAT waveformat;
SDL_RWread(rw, &waveformat, sizeof(waveformat), 1);
if (waveformat.wf.wFormatTag != WAVE_FORMAT_PCM) {
log_verbose("Not in proper format");
return false;
}
format.freq = waveformat.wf.nSamplesPerSec;
switch (waveformat.wBitsPerSample) {
case 8:
format.format = AUDIO_U8;
break;
case 16:
format.format = AUDIO_S16LSB;
break;
default:
log_verbose("Invalid bits per sample");
return false;
break;
}
format.channels = waveformat.wf.nChannels;
const Uint32 DATA = 0x61746164;
Uint32 datachunk_size = FindChunk(rw, DATA);
if (!datachunk_size) {
log_verbose("Could not find DATA chunk");
return false;
}
length = datachunk_size;
databegin = SDL_RWtell(rw);
return true;
}
Uint32 Source_SampleStream::FindChunk(SDL_RWops* rw, Uint32 wanted_id)
{
Uint32 subchunk_id = SDL_ReadLE32(rw);
Uint32 subchunk_size = SDL_ReadLE32(rw);
if (subchunk_id == wanted_id) {
return subchunk_size;
}
const Uint32 FACT = 0x74636166;
const Uint32 LIST = 0x5453494c;
const Uint32 BEXT = 0x74786562;
const Uint32 JUNK = 0x4B4E554A;
while (subchunk_id == FACT || subchunk_id == LIST || subchunk_id == BEXT || subchunk_id == JUNK) {
SDL_RWseek(rw, subchunk_size, RW_SEEK_CUR);
subchunk_id = SDL_ReadLE32(rw);
subchunk_size = SDL_ReadLE32(rw);
if (subchunk_id == wanted_id) {
return subchunk_size;
}
}
return 0;
}
unsigned long Stream::Length()
void Source_SampleStream::Unload()
{
switch(sourcetype) {
case SOURCE_SAMPLE:
return sample->Length();
break;
if (rw) {
SDL_RWclose(rw);
rw = NULL;
}
return 0;
}
void Stream::SetSource_Sample(Sample& sample)
{
sourcetype = SOURCE_SAMPLE;
Stream::sample = &sample;
}
const AudioFormat* Stream::Format()
{
switch(sourcetype) {
case SOURCE_SAMPLE:
return &sample->format;
break;
length = 0;
if (buffer) {
delete[] buffer;
buffer = 0;
}
return 0;
buffersize = 0;
}
Channel::Channel()
@ -223,7 +344,8 @@ Channel::Channel()
SetPan(0.5f);
done = true;
stopping = false;
stream = 0;
source = 0;
deletesourceondone = false;
}
Channel::~Channel()
@ -232,11 +354,14 @@ Channel::~Channel()
speex_resampler_destroy(resampler);
resampler = 0;
}
if (deletesourceondone) {
delete source;
}
}
void Channel::Play(Stream& stream, int loop = MIXER_LOOP_NONE)
void Channel::Play(Source& source, int loop = MIXER_LOOP_NONE)
{
Channel::stream = &stream;
Channel::source = &source;
Channel::loop = loop;
offset = 0;
done = false;
@ -286,14 +411,25 @@ unsigned long Channel::GetOffset()
bool Channel::SetOffset(unsigned long offset)
{
if (stream && offset < stream->Length()) {
int samplesize = stream->Format()->channels * stream->Format()->BytesPerSample();
if (source && offset < source->Length()) {
int samplesize = source->Format().channels * source->Format().BytesPerSample();
Channel::offset = (offset / samplesize) * samplesize;
return true;
}
return false;
}
Mixer::Mixer()
{
effectbuffer = 0;
for (int i = 0; i < countof(css1sources); i++) {
css1sources[i] = 0;
}
for (int i = 0; i < countof(musicsources); i++) {
musicsources[i] = 0;
}
}
void Mixer::Init(const char* device)
{
Close();
@ -310,10 +446,15 @@ void Mixer::Init(const char* device)
format.channels = have.channels;
format.freq = have.freq;
const char* filename = get_file_path(PATH_ID_CSS1);
for (int i = 0; i < SOUND_MAXID; i++) {
css1samples[i].LoadCSS1(filename, i);
css1samples[i].Convert(format); // convert to audio output format, saves some cpu usage but requires a bit more memory, optional
css1streams[i].SetSource_Sample(css1samples[i]);
for (int i = 0; i < countof(css1sources); i++) {
Source_Sample* source_sample = new Source_Sample;
if (source_sample->LoadCSS1(filename, i)) {
source_sample->Convert(format); // convert to audio output format, saves some cpu usage but requires a bit more memory, optional
css1sources[i] = source_sample;
} else {
css1sources[i] = &source_null;
delete source_sample;
}
}
effectbuffer = new uint8[(have.samples * format.BytesPerSample() * format.channels)];
SDL_PauseAudioDevice(deviceid, 0);
@ -328,7 +469,22 @@ void Mixer::Close()
}
Unlock();
SDL_CloseAudioDevice(deviceid);
delete[] effectbuffer;
for (int i = 0; i < countof(css1sources); i++) {
if (css1sources[i] && css1sources[i] != &source_null) {
delete css1sources[i];
css1sources[i] = 0;
}
}
for (int i = 0; i < countof(musicsources); i++) {
if (musicsources[i] && musicsources[i] != &source_null) {
delete musicsources[i];
musicsources[i] = 0;
}
}
if (effectbuffer) {
delete[] effectbuffer;
effectbuffer = 0;
}
}
void Mixer::Lock()
@ -341,13 +497,14 @@ void Mixer::Unlock()
SDL_UnlockAudioDevice(deviceid);
}
Channel* Mixer::Play(Stream& stream, int loop, bool deleteondone)
Channel* Mixer::Play(Source& source, int loop, bool deleteondone, bool deletesourceondone)
{
Lock();
Channel* newchannel = new (std::nothrow) Channel();
Channel* newchannel = new (std::nothrow) Channel;
if (newchannel) {
newchannel->Play(stream, loop);
newchannel->Play(source, loop);
newchannel->deleteondone = deleteondone;
newchannel->deletesourceondone = deletesourceondone;
newchannel->stopping = false;
channels.push_back(newchannel);
}
@ -364,13 +521,20 @@ void Mixer::Stop(Channel& channel)
bool Mixer::LoadMusic(int pathid)
{
if (pathid >= PATH_ID_END) {
if (pathid >= countof(musicsources)) {
return false;
}
if (!musicsamples[pathid].Loaded()) {
if (!musicsources[pathid]) {
const char* filename = get_file_path(pathid);
musicstreams[pathid].SetSource_Sample(musicsamples[pathid]);
return musicsamples[pathid].Load(filename);
Source_Sample* source_sample = new Source_Sample;
if (source_sample->LoadWAV(filename)) {
musicsources[pathid] = source_sample;
return true;
} else {
delete source_sample;
musicsources[pathid] = &source_null;
return false;
}
} else {
return true;
}
@ -394,8 +558,8 @@ void SDLCALL Mixer::Callback(void* arg, uint8* stream, int length)
void Mixer::MixChannel(Channel& channel, uint8* data, int length)
{
if (channel.stream && !channel.done) {
AudioFormat streamformat = *channel.stream->Format();
if (channel.source && channel.source->Length() > 0 && !channel.done) {
AudioFormat streamformat = channel.source->Format();
int loaded = 0;
SDL_AudioCVT cvt;
cvt.len_ratio = 1;
@ -409,9 +573,9 @@ void Mixer::MixChannel(Channel& channel, uint8* data, int length)
}
int samplestoread = (int)((samples - samplesloaded) * rate);
int lengthloaded = 0;
if (channel.offset < channel.stream->Length()) {
if (channel.offset < channel.source->Length()) {
bool mustconvert = false;
if (MustConvert(*channel.stream)) {
if (MustConvert(*channel.source)) {
if (SDL_BuildAudioCVT(&cvt, streamformat.format, streamformat.channels, streamformat.freq, Mixer::format.format, Mixer::format.channels, Mixer::format.freq) == -1) {
break;
}
@ -420,7 +584,7 @@ void Mixer::MixChannel(Channel& channel, uint8* data, int length)
const uint8* datastream = 0;
int toread = (int)(samplestoread / cvt.len_ratio) * samplesize;
int readfromstream = (channel.stream->GetSome(channel.offset, &datastream, toread));
int readfromstream = (channel.source->GetSome(channel.offset, &datastream, toread));
if (readfromstream == 0) {
break;
}
@ -519,7 +683,7 @@ void Mixer::MixChannel(Channel& channel, uint8* data, int length)
loaded += lengthloaded;
if (channel.loop != 0 && channel.offset >= channel.stream->Length()) {
if (channel.loop != 0 && channel.offset >= channel.source->Length()) {
if (channel.loop != -1) {
channel.loop--;
}
@ -528,7 +692,7 @@ void Mixer::MixChannel(Channel& channel, uint8* data, int length)
} while(loaded < length && channel.loop != 0 && !channel.stopping);
channel.oldvolume = channel.volume;
if (channel.loop == 0 && channel.offset >= channel.stream->Length()) {
if (channel.loop == 0 && channel.offset >= channel.source->Length()) {
channel.done = true;
}
}
@ -574,13 +738,10 @@ void Mixer::EffectFadeU8(uint8* data, int length, int startvolume, int endvolume
}
}
bool Mixer::MustConvert(Stream& stream)
bool Mixer::MustConvert(Source& source)
{
const AudioFormat* streamformat = stream.Format();
if (!streamformat) {
return false;
}
if (streamformat->format != format.format || streamformat->channels != format.channels || streamformat->freq != format.freq) {
const AudioFormat sourceformat = source.Format();
if (sourceformat.format != format.format || sourceformat.channels != format.channels || sourceformat.freq != format.freq) {
return true;
}
return false;
@ -609,11 +770,11 @@ void Mixer_Init(const char* device)
void* Mixer_Play_Effect(int id, int loop, int volume, float pan, double rate, int deleteondone)
{
if (id >= SOUND_MAXID) {
if (id >= countof(gMixer.css1sources)) {
return 0;
}
gMixer.Lock();
Channel* channel = gMixer.Play(gMixer.css1streams[id], loop, deleteondone != 0);
Channel* channel = gMixer.Play(*gMixer.css1sources[id], loop, deleteondone != 0, false);
if (channel) {
channel->SetVolume(volume);
channel->SetPan(pan);
@ -664,10 +825,33 @@ int Mixer_Channel_SetOffset(void* channel, unsigned long offset)
return ((Channel*)channel)->SetOffset(offset);
}
void* Mixer_Play_Music(int pathid)
void* Mixer_Play_Music(int pathid, int streaming)
{
if (gMixer.LoadMusic(pathid)) {
return gMixer.Play(gMixer.musicstreams[pathid], MIXER_LOOP_INFINITE, false);
if (streaming) {
const char* filename = get_file_path(pathid);
utf8 utf8filename[512];
win1252_to_utf8(utf8filename, filename, sizeof(utf8filename));
SDL_RWops* rw = SDL_RWFromFile(utf8filename, "rb");
if (rw == NULL) {
return 0;
}
Source_SampleStream* source_samplestream = new Source_SampleStream;
if (source_samplestream->LoadWAV(rw)) {
Channel* channel = gMixer.Play(*source_samplestream, MIXER_LOOP_INFINITE, false, true);
if (!channel) {
delete source_samplestream;
}
return channel;
} else {
delete source_samplestream;
return 0;
}
} else {
if (gMixer.LoadMusic(pathid)) {
return gMixer.Play(*gMixer.musicsources[pathid], MIXER_LOOP_INFINITE, false, false);
}
}
return 0;
}

View File

@ -43,45 +43,73 @@ struct AudioFormat {
int channels;
};
class Sample
class Source
{
public:
Sample();
~Sample();
bool Load(const char* filename);
bool LoadCSS1(const char* filename, unsigned int offset);
void Unload();
bool Loaded();
bool Convert(AudioFormat format);
const uint8* Data();
unsigned long Length();
friend class Stream;
private:
AudioFormat format;
uint8* data;
unsigned long length;
bool issdlwav;
};
class Stream
{
public:
Stream();
virtual ~Source();
unsigned long GetSome(unsigned long offset, const uint8** data, unsigned long length);
unsigned long Length();
void SetSource_Sample(Sample& sample);
const AudioFormat* Format();
const AudioFormat& Format();
friend class Mixer;
protected:
virtual unsigned long Read(unsigned long offset, const uint8** data, unsigned long length) = 0;
AudioFormat format;
unsigned long length;
};
class Source_Null : public Source
{
public:
Source_Null();
protected:
unsigned long Read(unsigned long offset, const uint8** data, unsigned long length);
};
class Source_Sample : public Source
{
public:
Source_Sample();
~Source_Sample();
bool LoadWAV(const char* filename);
bool LoadCSS1(const char* filename, unsigned int offset);
friend class Mixer;
protected:
bool Convert(AudioFormat format);
private:
enum {
SOURCE_NONE = 0,
SOURCE_SAMPLE
} sourcetype;
Sample* sample;
void Unload();
uint8* data;
bool issdlwav;
protected:
unsigned long Read(unsigned long offset, const uint8** data, unsigned long length);
};
class Source_SampleStream : public Source
{
public:
Source_SampleStream();
~Source_SampleStream();
bool LoadWAV(SDL_RWops* rw);
private:
Uint32 FindChunk(SDL_RWops* rw, Uint32 wanted_id);
void Unload();
SDL_RWops* rw;
Uint64 databegin;
uint8* buffer;
unsigned long buffersize;
protected:
unsigned long Read(unsigned long offset, const uint8** data, unsigned long length);
};
class Channel
@ -89,7 +117,7 @@ class Channel
public:
Channel();
~Channel();
void Play(Stream& stream, int loop);
void Play(Source& source, int loop);
void SetRate(double rate);
void SetVolume(int volume);
void SetPan(float pan);
@ -108,25 +136,27 @@ private:
float pan;
bool done;
bool deleteondone;
bool deletesourceondone;
bool stopping;
int oldvolume;
SpeexResamplerState* resampler;
Stream* stream;
Source* source;
};
class Mixer
{
public:
Mixer();
void Init(const char* device);
void Close();
void Lock();
void Unlock();
Channel* Play(Stream& stream, int loop, bool deleteondone);
Channel* Play(Source& source, int loop, bool deleteondone, bool deletesourceondone);
void Stop(Channel& channel);
bool LoadMusic(int pathid);
Stream css1streams[SOUND_MAXID];
Stream musicstreams[PATH_ID_END];
Source* css1sources[SOUND_MAXID];
Source* musicsources[PATH_ID_END];
private:
static void SDLCALL Callback(void* arg, uint8* data, int length);
@ -135,14 +165,13 @@ private:
void EffectPanU8(Channel& channel, uint8* data, int length);
void EffectFadeS16(sint16* data, int length, int startvolume, int endvolume);
void EffectFadeU8(uint8* data, int length, int startvolume, int endvolume);
bool MustConvert(Stream& stream);
bool MustConvert(Source& source);
bool Convert(SDL_AudioCVT& cvt, const uint8* data, unsigned long length, uint8** dataout);
SDL_AudioDeviceID deviceid;
AudioFormat format;
uint8* effectbuffer;
Sample css1samples[SOUND_MAXID];
Sample musicsamples[PATH_ID_END];
std::list<Channel*> channels;
Source_Null source_null;
};
extern "C"
@ -158,7 +187,7 @@ void Mixer_Channel_Rate(void* channel, double rate);
int Mixer_Channel_IsPlaying(void* channel);
unsigned long Mixer_Channel_GetOffset(void* channel);
int Mixer_Channel_SetOffset(void* channel, unsigned long offset);
void* Mixer_Play_Music(int pathid);
void* Mixer_Play_Music(int pathid, int streaming);
static int DStoMixerVolume(int volume) { return (int)(SDL_MIX_MAXVOLUME * (SDL_pow(10, (float)volume / 2000))); };
static float DStoMixerPan(int pan) { return (((float)pan + -DSBPAN_LEFT) / DSBPAN_RIGHT) / 2; };

View File

@ -265,7 +265,7 @@ void sub_6BD3A4()
for (int i = 200; i < 204; i++)
RCT2_ADDRESS(RCT2_ADDRESS_STAFF_MODE_ARRAY, uint8)[i] = STAFF_MODE_WALK;
sub_6C0C3F();
staff_update_greyed_patrol_areas();
}
/**

View File

@ -358,7 +358,7 @@ static int game_check_affordability(int cost)
}
RCT2_GLOBAL(0x13CE952, uint32) = cost;
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 827;
return 0x80000000;
return MONEY32_UNDEFINED;
}
static uint32 game_do_command_table[58];
@ -411,13 +411,13 @@ int game_do_command_p(int command, int *eax, int *ebx, int *ecx, int *edx, int *
}
cost = *ebx;
if (cost != 0x80000000) {
if (cost != MONEY32_UNDEFINED) {
// Check funds
insufficientFunds = 0;
if (RCT2_GLOBAL(0x009A8C28, uint8) == 1 && !(flags & 4) && !(flags & 0x20) && cost != 0)
insufficientFunds = game_check_affordability(cost);
if (insufficientFunds != 0x80000000) {
if (insufficientFunds != MONEY32_UNDEFINED) {
*ebx = original_ebx;
*edx = original_edx;
*esi = original_esi;
@ -438,7 +438,7 @@ int game_do_command_p(int command, int *eax, int *ebx, int *ecx, int *edx, int *
}
*edx = *ebx;
if (*edx != 0x80000000 && *edx < cost)
if (*edx != MONEY32_UNDEFINED && *edx < cost)
cost = *edx;
// Decrement nest count
@ -470,7 +470,7 @@ int game_do_command_p(int command, int *eax, int *ebx, int *ecx, int *edx, int *
if (RCT2_GLOBAL(0x009A8C28, uint8) == 0 && (flags & 1) && RCT2_GLOBAL(0x0141F568, uint8) == RCT2_GLOBAL(0x013CA740, uint8) && !(flags & 8))
window_error_open(RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16), RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16));
return 0x80000000;
return MONEY32_UNDEFINED;
}
void pause_toggle()
@ -797,7 +797,7 @@ char save_game()
path_set_extension(path, ".SV6");
if (scenario_save(path, gConfigGeneral.save_plugin_data ? 1 : 0)) {
game_do_command(0, 1047, 0, -1, GAME_COMMAND_0, 0, 0);
game_do_command(0, 1047, 0, -1, GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0);
gfx_invalidate_screen();
return 1;
} else {
@ -874,21 +874,21 @@ void game_load_or_quit_no_save_prompt()
#pragma region Game command function table
static uint32 game_do_command_table[58] = {
0x006B2FC5,
0,
0x0066397F,
0,
0x006C511D,
0x006C5B69,
0,
0x006B3F0F,
0x006B49D9,
0,
0,
0x006B52D4,
0, // 10
0,
0x006660A8,
0x0066640B,
0x006E0E01,
0,
0x006E08F4,
0x006E650F,
0,
@ -897,17 +897,17 @@ static uint32 game_do_command_table[58] = {
0, // use new_game_command_table, original: 0x00663CCD, // 20
0x006B53E9,
0x00698D6C, // text input
0x0068C542,
0x0068C6D1,
0,
0,
0x0068BC01,
0x006E66A0,
0x006E6878,
0,
0,
0x006C5AE9,
0, // use new_game_command_table, original: 0x006BEFA1, 29
0x006C09D1, // 30
0x006C0B83,
0x006C0BB5,
0x00669C6D,
0, // 30
0,
0,
0,
0,
0x006649BD,
0x006666E7,
@ -916,20 +916,20 @@ static uint32 game_do_command_table[58] = {
0,
0, // 40
0x006E519A,
0x006E5597,
0,
0x006B893C,
0x006B8E1B,
0,
0,
0,
0x006D13FE,
0,
0x006CDEE4,
0x006B9E6D, // 50
0x006BA058,
0x006E0F26,
0x006E56B5,
0x006B909A,
0x006BA16A,
0, // 50
0,
0,
0,
0,
0,
0x006648E3,
0
};
@ -937,21 +937,21 @@ static uint32 game_do_command_table[58] = {
void game_command_emptysub(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) {}
static GAME_COMMAND_POINTER* new_game_command_table[58] = {
game_command_emptysub,
game_command_set_ride_appearance,
game_command_emptysub,
game_pause_toggle,
game_command_emptysub,
game_command_emptysub,
game_load_or_quit,
game_command_emptysub,
game_command_emptysub,
game_command_demolish_ride,
game_command_set_ride_status,
game_command_emptysub,
game_command_set_ride_name, // 10
game_command_set_ride_setting,
game_command_emptysub,
game_command_emptysub,
game_command_emptysub,
game_command_remove_scenery,
game_command_emptysub,
game_command_emptysub,
game_command_place_footpath,
@ -960,16 +960,16 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = {
game_command_change_surface_style, // 20
game_command_emptysub,
game_command_emptysub,
game_command_raise_land,
game_command_lower_land,
game_command_emptysub,
game_command_emptysub,
game_command_emptysub,
game_command_emptysub,
game_command_emptysub,
game_command_raise_water,
game_command_lower_water,
game_command_emptysub,
game_command_hire_new_staff_member, //game_command_emptysub,
game_command_emptysub, // 30
game_command_emptysub,
game_command_emptysub,
game_command_set_staff_patrol, // 30
game_command_fire_staff_member,
game_command_set_staff_order,
game_command_set_park_name,
game_command_set_park_open,
game_command_emptysub,
@ -979,20 +979,20 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = {
game_command_set_park_entrance_fee,
game_command_update_staff_colour, // 40
game_command_emptysub,
game_command_remove_fence,
game_command_emptysub,
game_command_emptysub,
game_command_emptysub,
game_command_remove_large_scenery,
game_command_set_current_loan,
game_command_set_research_funding,
game_command_emptysub,
game_command_start_campaign,
game_command_emptysub,
game_command_emptysub, // 50
game_command_emptysub,
game_command_emptysub,
game_command_emptysub,
game_command_emptysub,
game_command_emptysub,
game_command_place_banner, // 50
game_command_remove_banner,
game_command_set_scenery_colour,
game_command_set_fence_colour,
game_command_set_large_scenery_colour,
game_command_set_banner_colour,
game_command_emptysub,
game_command_clear_scenery
};

View File

@ -24,7 +24,7 @@
#include "common.h"
enum GAME_COMMAND {
GAME_COMMAND_0,
GAME_COMMAND_SET_RIDE_APPEARANCE,
GAME_COMMAND_1,
GAME_COMMAND_TOGGLE_PAUSE, // 2
GAME_COMMAND_3, //Has something to do with ride construction
@ -68,14 +68,14 @@ enum GAME_COMMAND {
GAME_COMMAND_41,
GAME_COMMAND_REMOVE_FENCE,
GAME_COMMAND_43,
GAME_COMMAND_44,
GAME_COMMAND_REMOVE_LARGE_SCENERY,
GAME_COMMAND_SET_CURRENT_LOAN, // 45
GAME_COMMAND_SET_RESEARCH_FUNDING, // 46
GAME_COMMAND_47,
GAME_COMMAND_START_MARKETING_CAMPAIGN, // 48
GAME_COMMAND_49,
GAME_COMMAND_50, // New banner? (possibly scenery)
GAME_COMMAND_51, // Remove banner
GAME_COMMAND_PLACE_BANNER, // New banner? (possibly scenery)
GAME_COMMAND_REMOVE_BANNER, // Remove banner
GAME_COMMAND_52,
GAME_COMMAND_53,
GAME_COMMAND_54,

View File

@ -512,7 +512,7 @@ static void viewport_interaction_remove_large_scenery(rct_map_element *mapElemen
1 | ((mapElement->type & 0x3) << 8),
y,
mapElement->base_height | ((mapElement->properties.scenerymultiple.type >> 10) << 8),
GAME_COMMAND_44,
GAME_COMMAND_REMOVE_LARGE_SCENERY,
0,
0
);

View File

@ -192,6 +192,8 @@ enum {
STR_LOCATE_SUBJECT_TIP = 1027,
STR_OFF_EDGE_OF_MAP = 1028,
STR_CAN_ONLY_BUILD_THIS_ON_LAND = 1034,
STR_LOAD_GAME_DIALOG_TITLE = 1036,
STR_LOAD_LANDSCAPE_DIALOG_TITLE = 1037,
STR_CONVERT_SAVED_GAME_TO_SCENARIO_1038 = 1038,
@ -319,6 +321,7 @@ enum {
STR_BUILD_FOOTPATH_TIP = 1173,
STR_BANNER_SIGN_IN_THE_WAY = 1174,
STR_CANT_BUILD_THIS_ON_SLOPED_FOOTPATH = 1175,
STR_CANT_BUILD_FOOTPATH_HERE = 1176,
STR_CANT_REMOVE_FOOTPATH_FROM_HERE = 1177,
@ -377,6 +380,7 @@ enum {
STR_SHOPS_STALLS_TIP = 1228,
STR_ROTATE_OBJECTS_90 = 1327,
STR_LEVEL_LAND_REQUIRED = 1328,
STR_LAUNCH_SPEED = 1329,
STR_LAUNCH_SPEED_TIP = 1330,
@ -739,6 +743,8 @@ enum {
STR_CANT_DEMOLISH_RIDE = 2248,
STR_CAN_ONLY_BE_BUILT_ACROSS_PATHS = 2252,
STR_RESEARCH_TRANSPORT_RIDES = 2253,
STR_RESEARCH_GENTLE_RIDES = 2254,
STR_RESEARCH_ROLLER_COASTERS = 2255,
@ -1066,6 +1072,8 @@ enum {
STR_MUSIC_ACKNOWLEDGEMENTS_ELLIPSIS = 2862,
STR_MUSIC_ACKNOWLEDGEMENTS = 2863,
STR_TOO_MANY_BANNERS_IN_GAME = 2980,
STR_CHANGE_BANNER_TEXT_TIP = 2986,
STR_SET_AS_NO_ENTRY_BANNER_TIP = 2987,
STR_DEMOLISH_BANNER_TIP = 2988,

View File

@ -26,7 +26,7 @@
typedef int rct_expenditure_type;
enum {
RCT_EXPENDITURE_TYPE_RIDE_CONSRUCTION,
RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION,
RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS,
RCT_EXPENDITURE_TYPE_LAND_PURCHASE,
RCT_EXPENDITURE_TYPE_LANDSCAPING,

View File

@ -907,10 +907,11 @@ int paint_large_scenery(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo*
chunk += 1038;
}
scenery_type->large_scenery.var_0C = (uint32)chunk;
scenery_type->large_scenery.tiles = (rct_large_scenery_tile*)chunk;
// skip over large scenery tiles
while (*((uint16*)chunk) != 0xFFFF){
chunk += 9;
chunk += sizeof(rct_large_scenery_tile);
}
chunk += 2;
@ -937,7 +938,7 @@ int paint_large_scenery(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo*
rct_scenery_entry* scenery_type = (rct_scenery_entry*)esi;
scenery_type->name = 0;
scenery_type->image = 0;
scenery_type->large_scenery.var_0C = 0;
scenery_type->large_scenery.tiles = 0;
scenery_type->large_scenery.scenery_tab_id = 0;
scenery_type->large_scenery.var_12 = 0;
scenery_type->large_scenery.var_16 = 0;

View File

@ -175,6 +175,21 @@ static void sub_693BE5(rct_peep* peep, uint8 al){
sub_693B58(peep);
}
/**
*
* rct2: 0x0069A512
*/
void remove_peep_from_ride(rct_peep* peep)
{
if (peep->state == PEEP_STATE_QUEUING) {
remove_peep_from_queue(peep);
}
peep_decrement_num_riders(peep);
peep->state = PEEP_STATE_1;
peep_window_state_update(peep);
sub_693BE5(peep, 0);
}
static void peep_state_reset(rct_peep* peep){
peep_decrement_num_riders(peep);
peep->state = PEEP_STATE_1;
@ -556,7 +571,7 @@ void peep_sprite_remove(rct_peep* peep){
//RCT2_CALLPROC_X(0x69A535, 0, 0, 0, 0, (int)peep, 0, 0);
//return;
RCT2_CALLPROC_X(0x0069A512, 0, 0, 0, 0, (int)peep, 0, 0);
remove_peep_from_ride(peep);
invalidate_sprite((rct_sprite*)peep);
window_close_by_number(WC_PEEP, peep->sprite_index);
@ -573,7 +588,7 @@ void peep_sprite_remove(rct_peep* peep){
RCT2_ADDRESS(RCT2_ADDRESS_STAFF_MODE_ARRAY, uint8)[peep->staff_id] = 0;
peep->type = 0xFF;
sub_6C0C3F();
staff_update_greyed_patrol_areas();
peep->type = PEEP_TYPE_STAFF;
news_item_disable_news(NEWS_ITEM_PEEP, peep->sprite_index);
@ -4562,7 +4577,7 @@ void peep_update_crowd_noise()
// Load and play crowd noise
#ifdef USE_MIXER
if (!gCrowdSoundChannel) {
gCrowdSoundChannel = Mixer_Play_Music(PATH_ID_CSS2);
gCrowdSoundChannel = Mixer_Play_Music(PATH_ID_CSS2, false);
}
if (gCrowdSoundChannel) {
Mixer_Channel_Volume(gCrowdSoundChannel, DStoMixerVolume(volume));

View File

@ -570,6 +570,7 @@ int peep_check_easteregg_name(int index, rct_peep *peep);
int peep_get_easteregg_name_id(rct_peep *peep);
int peep_is_mechanic(rct_peep *peep);
int peep_has_food(rct_peep* peep);
void peep_sprite_remove(rct_peep* peep);
void peep_window_state_update(rct_peep* peep);
void peep_decrement_num_riders(rct_peep* peep);
@ -583,6 +584,7 @@ void peep_insert_new_thought(rct_peep *peep, uint8 thought_type, uint8 thought_a
void peep_set_map_tooltip(rct_peep *peep);
void sub_693B58(rct_peep* peep);
void remove_peep_from_ride(rct_peep* peep);
void remove_peep_from_queue(rct_peep* peep);
#endif

View File

@ -70,7 +70,7 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx,
RCT2_GLOBAL(0x009DEA62, uint16) = _dx;
if (RCT2_GLOBAL(0x13573C8, uint16) < 0x190) {
*ebx = 0x80000000;
*ebx = MONEY32_UNDEFINED;
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_TOO_MANY_PEOPLE_IN_GAME;
return;
}
@ -82,7 +82,7 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx,
}
if (i == STAFF_MAX_COUNT) {
*ebx = 0x80000000;
*ebx = MONEY32_UNDEFINED;
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_TOO_MANY_STAFF_IN_GAME;
return;
}
@ -96,7 +96,7 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx,
if (newPeep == NULL)
{
*ebx = 0x80000000;
*ebx = MONEY32_UNDEFINED;
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_TOO_MANY_PEOPLE_IN_GAME;
return;
}
@ -211,6 +211,95 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx,
*edi = newPeep->sprite_index;
}
/**
*
* rct2: 0x006C0BB5
*/
void game_command_set_staff_order(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp)
{
RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = 40;
uint8 order_id = *ebx >> 8;
uint16 sprite_id = *edx;
if(*ebx & GAME_COMMAND_FLAG_APPLY){
rct_peep *peep = &g_sprite_list[sprite_id].peep;
if(order_id & 0x80){ // change costume
uint8 sprite_type = order_id & ~0x80;
sprite_type += 4;
peep->sprite_type = sprite_type;
peep->flags &= ~PEEP_FLAGS_SLOW_WALK;
if(RCT2_ADDRESS(0x00982134, uint8)[sprite_type] & 1){
peep->flags |= PEEP_FLAGS_SLOW_WALK;
}
peep->action_frame = 0;
sub_693B58(peep);
invalidate_sprite((rct_sprite*)peep);
window_invalidate_by_number(WC_PEEP, sprite_id);
window_invalidate_by_class(WC_STAFF_LIST);
}else{
peep->staff_orders = order_id;
window_invalidate_by_number(WC_PEEP, sprite_id);
window_invalidate_by_class(WC_STAFF_LIST);
}
}
*ebx = 0;
}
/**
*
* rct2: 0x006C09D1
*/
void game_command_set_staff_patrol(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp)
{
if(*ebx & GAME_COMMAND_FLAG_APPLY){
int x = *eax;
int y = *ecx;
uint16 sprite_id = *edx;
rct_peep *peep = &g_sprite_list[sprite_id].peep;
int patrolOffset = peep->staff_id * (64 * 64 / 8);
int patrolIndex = ((x & 0x1F80) >> 7) | ((y & 0x1F80) >> 1);
int mask = 1 << (patrolIndex & 0x1F);
int base = patrolIndex >> 5;
uint32 *patrolBits = (uint32*)(0x013B0E72 + patrolOffset + (base * 4));
*patrolBits ^= mask;
int ispatrolling = 0;
for(int i = 0; i < 128; i++){
ispatrolling |= *(uint32*)(0x013B0E72 + patrolOffset + (i * 4));
}
RCT2_ADDRESS(RCT2_ADDRESS_STAFF_MODE_ARRAY, uint8)[peep->staff_id] &= ~2;
if(ispatrolling){
RCT2_ADDRESS(RCT2_ADDRESS_STAFF_MODE_ARRAY, uint8)[peep->staff_id] |= 2;
}
for(int y2 = 0; y2 < 4; y2++){
for(int x2 = 0; x2 < 4; x2++){
map_invalidate_tile_full((x & 0x1F80) + (x2 * 32), (y & 0x1F80) + (y2 * 32));
}
}
staff_update_greyed_patrol_areas();
}
*ebx = 0;
}
/**
*
* rct2: 0x006C0B83
*/
void game_command_fire_staff_member(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp)
{
RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = 40;
if(*ebx & GAME_COMMAND_FLAG_APPLY){
window_close_by_class(WC_FIRE_PROMPT);
uint16 sprite_id = *edx;
rct_peep *peep = &g_sprite_list[sprite_id].peep;
remove_peep_from_ride(peep);
peep_sprite_remove(peep);
}
*ebx = 0;
}
/*
* Updates the colour of the given staff type.
*/
@ -233,29 +322,33 @@ uint16 hire_new_staff_member(uint8 staffType)
int result = game_do_command_p(GAME_COMMAND_HIRE_NEW_STAFF_MEMBER, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
if (result == 0x80000000)
if (result == MONEY32_UNDEFINED)
return 0xFFFF;
return edi;
}
void sub_6C0C3F()
/**
*
* rct2: 0x006C0C3F
*/
void staff_update_greyed_patrol_areas()
{
register rct_peep* peep;
rct_peep* peep;
for (register uint8 staff_type = 0; staff_type < STAFF_TYPE_COUNT; ++staff_type)
for (int staff_type = 0; staff_type < STAFF_TYPE_COUNT; ++staff_type)
{
for (register uint8 i = 0; i < 128; ++i)
RCT2_ADDRESS(0x13B0E72 + (staff_type + STAFF_MAX_COUNT) * 512, uint32)[i] = 0;
for (int i = 0; i < 128; ++i)
RCT2_ADDRESS(0x13B0E72 + ((staff_type + STAFF_MAX_COUNT) * 512), uint32)[i] = 0;
for (register uint16 sprite_index = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16); sprite_index != SPRITE_INDEX_NULL; sprite_index = peep->next)
for (uint16 sprite_index = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16); sprite_index != SPRITE_INDEX_NULL; sprite_index = peep->next)
{
peep = GET_PEEP(sprite_index);
if (peep->type == PEEP_TYPE_STAFF && staff_type == peep->staff_type)
{
for (register uint8 i = 0; i < 128; ++i)
RCT2_ADDRESS(0x13B0E72 + (staff_type + STAFF_MAX_COUNT) * 512, uint32)[i] |= RCT2_ADDRESS(0x13B0E72 + peep->staff_id * 512, uint32)[i];
for (int i = 0; i < 128; ++i)
RCT2_ADDRESS(0x13B0E72 + ((staff_type + STAFF_MAX_COUNT) * 512), uint32)[i] |= RCT2_ADDRESS(0x13B0E72 + (peep->staff_id * 512), uint32)[i];
}
}

View File

@ -51,10 +51,13 @@ enum STAFF_ORDERS{
void game_command_update_staff_colour(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
void game_command_hire_new_staff_member(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
void game_command_set_staff_order(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
void game_command_set_staff_patrol(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
void game_command_fire_staff_member(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
void update_staff_colour(uint8 staffType, uint16 color);
uint16 hire_new_staff_member(uint8 staffType);
void sub_6C0C3F();
void staff_update_greyed_patrol_areas();
int mechanic_is_location_in_patrol(rct_peep *mechanic, int x, int y);
void staff_reset_stats();

View File

@ -27,12 +27,14 @@
#include "../localisation/date.h"
#include "../localisation/localisation.h"
#include "../management/finance.h"
#include "../management/marketing.h"
#include "../management/news_item.h"
#include "../peep/peep.h"
#include "../peep/staff.h"
#include "../scenario.h"
#include "../util/util.h"
#include "../windows/error.h"
#include "../world/banner.h"
#include "../world/map.h"
#include "../world/sprite.h"
#include "ride.h"
@ -556,7 +558,7 @@ int ride_create_ride(ride_list_item listItem)
esi = GAME_COMMAND_6;
game_do_command_p(esi, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
return ebx == 0x80000000 ? -1 : edi;
return ebx == MONEY32_UNDEFINED ? -1 : edi;
}
/**
@ -2660,7 +2662,7 @@ void ride_music_update_final()
rct_ride_music_info* ride_music_info = &RCT2_GLOBAL(0x009AF1C8, rct_ride_music_info*)[ride_music_params->tuneid];
#ifdef USE_MIXER
rct_ride_music* ride_music = &gRideMusicList[ebx];
ride_music->sound_channel = Mixer_Play_Music(ride_music_info->pathid);
ride_music->sound_channel = Mixer_Play_Music(ride_music_info->pathid, true);
if (ride_music->sound_channel) {
ride_music->volume = ride_music_params->volume;
ride_music->pan = ride_music_params->pan;
@ -2676,7 +2678,7 @@ void ride_music_update_final()
}
Mixer_Channel_SetOffset(ride_music->sound_channel, offset);
} else {
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8) = 0;
//RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8) = 0;
}
#else
const char* filename = get_file_path(ride_music_info->pathid);
@ -2781,13 +2783,13 @@ void game_command_set_ride_setting(int *eax, int *ebx, int *ecx, int *edx, int *
if (setting == 0){
if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN){
RCT2_GLOBAL(0x141E9AC, uint16) = 1796;
*ebx = 0x80000000;
*ebx = MONEY32_UNDEFINED;
return;
}
if (ride->status != RIDE_STATUS_CLOSED){
RCT2_GLOBAL(0x141E9AC, uint16) = 1006;
*ebx = 0x80000000;
*ebx = MONEY32_UNDEFINED;
return;
}
}
@ -2796,7 +2798,7 @@ void game_command_set_ride_setting(int *eax, int *ebx, int *ecx, int *edx, int *
if (setting == 0 || setting == 4 || setting == 8 || setting == 9)
{
RCT2_GLOBAL(0x141E9AC, uint16) = 1797;
*ebx = 0x80000000;
*ebx = MONEY32_UNDEFINED;
return;
}
}
@ -2805,7 +2807,7 @@ void game_command_set_ride_setting(int *eax, int *ebx, int *ecx, int *edx, int *
ride->lifecycle_flags & RIDE_LIFECYCLE_CABLE_LIFT &&
new_value > 1){
RCT2_GLOBAL(0x141E9AC, uint16) = 3141;
*ebx = 0x80000000;
*ebx = MONEY32_UNDEFINED;
return;
}
@ -3590,6 +3592,262 @@ void game_command_set_ride_name(int *eax, int *ebx, int *ecx, int *edx, int *esi
*ebx = 0;
}
/**
*
* rct2: 0x006CB7FB
*/
int ride_get_refund_price(int ride_id)
{
uint8 oldpaused = RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8);
RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) = 0;
RCT2_GLOBAL(0x00F4413A, int) = 0;
for(int x = 0; x < 8192; x += 32){
for(int y = 0; y < 8192; y += 32){
int tile_idx = ((y * 256) + x) / 32;
rct_map_element* map_element = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[tile_idx];
do{
if((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_TRACK && map_element->properties.track.ride_index == ride_id){
int eax, ebx, ecx, edx, esi, edi, ebp;
eax = x;
ebx = ((map_element->type & MAP_ELEMENT_DIRECTION_MASK) << 8) | 0x01;
ecx = y;
edx = map_element->properties.track.type;
edi = map_element->base_height * 8;
if(map_element->properties.track.type == 101){
edx = 2 << 8 | map_element->properties.track.ride_index;
int oldeax = eax;
int oldebx = ebx;
int oldecx = ecx;
int oldedx = edx;
ebx = oldebx;
ebx |= 0 << 0;
RCT2_GLOBAL(0x00F4413A, int) += game_do_command_p(GAME_COMMAND_38, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
ebx = oldebx;
ebx |= 1 << 8;
ecx = oldecx;
ecx += 16;
edx = oldedx;
RCT2_GLOBAL(0x00F4413A, int) += game_do_command_p(GAME_COMMAND_38, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
ebx = oldebx;
ebx |= 2 << 8;
eax = oldeax;
eax += 16;
ecx = oldecx;
ecx += 16;
edx = oldedx;
RCT2_GLOBAL(0x00F4413A, int) += game_do_command_p(GAME_COMMAND_38, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
ebx = oldebx;
ebx |= 3 << 8;
eax = oldeax;
eax += 16;
ecx = oldecx;
edx = oldedx;
RCT2_GLOBAL(0x00F4413A, int) += game_do_command_p(GAME_COMMAND_38, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
}else{
edx |= 0xFF << 8;
edx &= ((map_element->properties.track.sequence & 0xF) << 8) | 0xFF;
RCT2_GLOBAL(0x00F4413A, int) += game_do_command_p(GAME_COMMAND_4, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
}
y -= 32;
break;
}
map_element++;
}while(!((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE));
}
}
RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) = oldpaused;
return RCT2_GLOBAL(0x00F4413A, int);
}
/**
*
* rct2: 0x006B49D9
*/
void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp)
{
uint8 ride_id = *(uint8*)edx;
RCT2_GLOBAL(0x009DEA5E, uint16) = 0;
RCT2_GLOBAL(0x009DEA60, uint16) = 0;
RCT2_GLOBAL(0x009DEA62, uint16) = 0;
rct_ride *ride = &g_ride_list[ride_id];
int x = 0, y = 0, z = 0;
if(ride->overall_view != (uint16)-1){
x = ((ride->overall_view & 0xFF) * 32) + 16;
y = ((ride->overall_view >> 8) * 32) + 16;
z = map_element_height(x, y);
RCT2_GLOBAL(0x009DEA5E, uint16) = x;
RCT2_GLOBAL(0x009DEA60, uint16) = y;
RCT2_GLOBAL(0x009DEA62, uint16) = z;
}
if(!(*ebx & 0x40) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8)){
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED;
*ebx = MONEY32_UNDEFINED;
return;
}else{
if(*ebx & GAME_COMMAND_FLAG_APPLY){
if(!(*ebx & 8)){
window_close_by_number(WC_RIDE_CONSTRUCTION, ride_id);
}
window_close_by_number(WC_RIDE, ride_id);
window_close_by_number(WC_DEMOLISH_RIDE_PROMPT, ride_id);
window_close_by_class(WC_NEW_CAMPAIGN);
if(RCT2_GLOBAL(0x01358103, uint8) && ride_id == RCT2_GLOBAL(0x01358117, uint8)){
RCT2_GLOBAL(0x01358103, uint8) = 0;
}
if(RCT2_GLOBAL(0x01358107, uint8) && ride_id == RCT2_GLOBAL(0x0135811B, uint8)){
RCT2_GLOBAL(0x01358107, uint8) = 0;
}
ride_clear_for_construction(ride_id);
ride_remove_peeps(ride_id);
RCT2_CALLPROC_X(0x00696707, 0, 0, 0, ride_id, 0, 0, 0);
*ebx = ride_get_refund_price(ride_id);
RCT2_CALLPROC(0x006CB945);
news_item_disable_news(NEWS_ITEM_RIDE, ride_id);
for(int i = 0; i < MAX_BANNERS; i++){
rct_banner *banner = &gBanners[i];
if(banner->type != BANNER_NULL && banner->flags & BANNER_FLAG_2 && banner->colour == ride_id){
banner->flags &= 0xFB;
banner->string_idx = 778;
}
}
uint16 spriteIndex;
rct_peep *peep;
FOR_ALL_GUESTS(spriteIndex, peep){
uint8 ride_id_bit = ride_id & 0x3;
uint8 ride_id_offset = ride_id / 8;
peep->rides_been_on[ride_id_offset] &= ~(1 << ride_id_bit); // clear ride from potentially being in rides_been_on
if(peep->state == PEEP_STATE_WATCHING){
if(peep->current_ride == ride_id){
peep->current_ride = MAX_RIDES;
if(peep->time_to_stand >= 50){ // make peep stop watching the ride
peep->time_to_stand = 50;
}
}
}
// remove any free voucher for this ride from peep
if(peep->item_standard_flags & PEEP_ITEM_VOUCHER){
if(peep->voucher_type == VOUCHER_TYPE_RIDE_FREE && peep->voucher_arguments == ride_id){
peep->item_standard_flags &= ~(PEEP_ITEM_VOUCHER);
}
}
// remove any photos of this ride from peep
if(peep->item_standard_flags & PEEP_ITEM_PHOTO){
if(peep->photo1_ride_ref == ride_id){
peep->item_standard_flags &= ~PEEP_ITEM_PHOTO;
}
}
if(peep->item_extra_flags && PEEP_ITEM_PHOTO2){
if(peep->photo2_ride_ref == ride_id){
peep->item_extra_flags &= ~PEEP_ITEM_PHOTO2;
}
}
if(peep->item_extra_flags && PEEP_ITEM_PHOTO3){
if(peep->photo3_ride_ref == ride_id){
peep->item_extra_flags &= ~PEEP_ITEM_PHOTO3;
}
}
if(peep->item_extra_flags && PEEP_ITEM_PHOTO4){
if(peep->photo4_ride_ref == ride_id){
peep->item_extra_flags &= ~PEEP_ITEM_PHOTO4;
}
}
if(peep->guest_heading_to_ride_id == ride_id){
peep->guest_heading_to_ride_id = MAX_RIDES;
}
if(peep->favourite_ride == ride_id){
peep->favourite_ride = MAX_RIDES;
}
for (int i = 0; i < PEEP_MAX_THOUGHTS; i++) {
if(peep->thoughts[i].item == ride_id){
// Clear top thought, push others up
memmove(&peep->thoughts[i], &peep->thoughts[i + 1], sizeof(rct_peep_thought)*(PEEP_MAX_THOUGHTS - i - 1));
peep->thoughts[PEEP_MAX_THOUGHTS - 1].type = PEEP_THOUGHT_TYPE_NONE;
}
}
}
user_string_free(ride->name);
ride->type = RIDE_TYPE_NULL;
window_invalidate_by_class(WC_RIDE_LIST);
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_VALUE, money32) = calculate_park_value();
RCT2_GLOBAL(0x009DEA5E, uint16) = x;
RCT2_GLOBAL(0x009DEA60, uint16) = y;
RCT2_GLOBAL(0x009DEA62, uint16) = z;
RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION;
return;
}else{
*ebx = 0;
RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION;
return;
}
}
}
/**
*
* rct2: 0x006B2FC5
*/
void game_command_set_ride_appearance(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp)
{
if(*ebx & GAME_COMMAND_FLAG_APPLY){
uint8 ride_id = *edx;
uint8 type = *ebx >> 8;
uint8 value = *edx >> 8;
int index = *edi;
rct_ride *ride = &g_ride_list[ride_id];
switch(type){
case 0:
ride->track_colour_main[index] = value;
gfx_invalidate_screen();
break;
case 1:
ride->track_colour_additional[index] = value;
gfx_invalidate_screen();
break;
case 2:
*((uint8*)(&ride->vehicle_colours[index])) = value;
RCT2_CALLPROC_X(0x006DE102, 0, 0, 0, ride_id, 0, 0, 0);
break;
case 3:
*((uint8*)(&ride->vehicle_colours[index]) + 1) = value;
RCT2_CALLPROC_X(0x006DE102, 0, 0, 0, ride_id, 0, 0, 0);
break;
case 4:
ride->track_colour_supports[index] = value;
gfx_invalidate_screen();
break;
case 5:
ride->colour_scheme_type &= ~(RIDE_COLOUR_SCHEME_DIFFERENT_PER_TRAIN | RIDE_COLOUR_SCHEME_DIFFERENT_PER_CAR);
ride->colour_scheme_type |= value;
for(int i = 1; i < countof(ride->vehicle_colours); i++){
ride->vehicle_colours[i] = ride->vehicle_colours[0];
ride->vehicle_colours_extended[i] = ride->vehicle_colours_extended[0];
}
RCT2_CALLPROC_X(0x006DE102, 0, 0, 0, ride_id, 0, 0, 0);
break;
case 6:
ride->entrance_style = value;
RCT2_GLOBAL(0x01358840, uint8) = value;
gfx_invalidate_screen();
break;
case 7:
ride->vehicle_colours_extended[index] = value;
RCT2_CALLPROC_X(0x006DE102, 0, 0, 0, ride_id, 0, 0, 0);
break;
}
window_invalidate_by_number(WC_RIDE, ride_id);
}
*ebx = 0;
}
bool ride_type_has_flag(int rideType, int flag)
{
return (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (rideType * 8), uint32) & flag) != 0;

View File

@ -764,6 +764,9 @@ void game_command_set_ride_status(int *eax, int *ebx, int *ecx, int *edx, int *e
void ride_set_name(int rideIndex, const char *name);
void game_command_set_ride_name(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
void game_command_set_ride_setting(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
int ride_get_refund_price(int ride_id);
void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
void game_command_set_ride_appearance(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
int get_var_10E_unk_1(rct_ride* ride);
int get_var_10E_unk_2(rct_ride* ride);

View File

@ -784,7 +784,7 @@ int sub_6D2189(int* cost, uint8* ride_id){
edx = track_design->type | (entry_index << 8);
esi = GAME_COMMAND_6;
if (0x80000000 == game_do_command_p(GAME_COMMAND_6, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp)) return 1;
if (MONEY32_UNDEFINED == game_do_command_p(GAME_COMMAND_6, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp)) return 1;
// bh
*ride_id = edi & 0xFF;
@ -840,7 +840,7 @@ int sub_6D2189(int* cost, uint8* ride_id){
edi = sub_6D01B3((*ride_id << 8) | bl, map_size, map_size, z);
RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) = backup_park_flags;
if (edi != 0x80000000){
if (edi != MONEY32_UNDEFINED){
if (!find_object_in_entry_group(&track_design->vehicle_object, &entry_type, &entry_index)){
RCT2_GLOBAL(0xF44151, uint8) |= 4;

View File

@ -314,7 +314,7 @@ int scenario_load_and_play_from_path(const char *path)
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PROFIT, money32) = 0;
RCT2_GLOBAL(0x01358334, money32) = 0;
RCT2_GLOBAL(0x01358338, uint16) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_COMPLETED_COMPANY_VALUE, uint32) = 0x80000000;
RCT2_GLOBAL(RCT2_ADDRESS_COMPLETED_COMPANY_VALUE, uint32) = MONEY32_UNDEFINED;
RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_ADMISSIONS, uint32) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_INCOME_FROM_ADMISSIONS, uint32) = 0;
RCT2_GLOBAL(0x013587D8, uint16) = 63;
@ -517,7 +517,7 @@ void scenario_objectives_check()
park_value = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_VALUE, sint32);
if ( scenario_completed_company_value != 0x80000000)
if ( scenario_completed_company_value != MONEY32_UNDEFINED)
return;
switch (objective_type) {

View File

@ -201,7 +201,7 @@ static void window_banner_mouseup()
window_close(w);
break;
case WIDX_BANNER_DEMOLISH:
game_do_command(x, 1, y, map_element->base_height | (map_element->properties.banner.position << 8), GAME_COMMAND_51, 0, 0);
game_do_command(x, 1, y, map_element->base_height | (map_element->properties.banner.position << 8), GAME_COMMAND_REMOVE_BANNER, 0, 0);
break;
case WIDX_BANNER_TEXT:
window_text_input_open(w, WIDX_BANNER_TEXT, 2982, 2983, gBanners[w->number].string_idx, 0, 32);

View File

@ -103,7 +103,7 @@ void window_clear_scenery_open()
window_init_scroll_widgets(window);
window_push_others_below(window);
RCT2_GLOBAL(0x00F1AD62, uint32) = 0x80000000;
RCT2_GLOBAL(0x00F1AD62, uint32) = MONEY32_UNDEFINED;
window->colours[0] = 24;
window->colours[1] = 24;
window->colours[2] = 24;
@ -209,7 +209,7 @@ static void window_clear_scenery_paint()
// Draw cost amount
x = (window_clear_scenery_widgets[WIDX_PREVIEW].left + window_clear_scenery_widgets[WIDX_PREVIEW].right) / 2 + w->x;
y = window_clear_scenery_widgets[WIDX_PREVIEW].bottom + w->y + 5;
if (RCT2_GLOBAL(0x00F1AD62, uint32) != 0x80000000 && RCT2_GLOBAL(0x00F1AD62, uint32) != 0)
if (RCT2_GLOBAL(0x00F1AD62, uint32) != MONEY32_UNDEFINED && RCT2_GLOBAL(0x00F1AD62, uint32) != 0)
gfx_draw_string_centred(dpi, 986, x, y, 0, (void*)0x00F1AD62);
}

View File

@ -865,7 +865,7 @@ static void window_finances_financial_graph_paint()
money32 *balanceHistory = RCT2_ADDRESS(RCT2_ADDRESS_BALANCE_HISTORY, money32);
for (i = 0; i < 64; i++) {
money32 balance = balanceHistory[i];
if (balance == 0x80000000)
if (balance == MONEY32_UNDEFINED)
continue;
// Modifier balance then keep halfing until less than 127 pixels
@ -983,7 +983,7 @@ static void window_finances_park_value_graph_paint()
money32 *parkValueHistory = RCT2_ADDRESS(RCT2_ADDRESS_PARK_VALUE_HISTORY, money32);
for (i = 0; i < 64; i++) {
money32 balance = parkValueHistory[i];
if (balance == 0x80000000)
if (balance == MONEY32_UNDEFINED)
continue;
// Modifier balance then keep halfing until less than 255 pixels
@ -1101,7 +1101,7 @@ static void window_finances_profit_graph_paint()
money32 *weeklyProfitHistory = RCT2_ADDRESS(RCT2_ADDRESS_WEEKLY_PROFIT_HISTORY, money32);
for (i = 0; i < 64; i++) {
money32 balance = weeklyProfitHistory[i];
if (balance == 0x80000000)
if (balance == MONEY32_UNDEFINED)
continue;
// Modifier balance then keep halfing until less than 127 pixels

View File

@ -622,7 +622,7 @@ void window_guest_overview_mouse_up(){
w->var_48C = peep->x;
RCT2_CALLPROC_X(0x0069A512, 0, 0, 0, 0, (int)peep, 0, 0);
remove_peep_from_ride(peep);
invalidate_sprite((rct_sprite*)peep);
sprite_move(0x8000, peep->y, peep->z, (rct_sprite*)peep);

View File

@ -605,7 +605,7 @@ static void window_loadsave_select(rct_window *w, const char *path)
if (scenario_save((char*)path, gConfigGeneral.save_plugin_data ? 1 : 0)) {
window_close(w);
game_do_command(0, 1047, 0, -1, GAME_COMMAND_0, 0, 0);
game_do_command(0, 1047, 0, -1, GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0);
gfx_invalidate_screen();
}
else {

View File

@ -3808,22 +3808,22 @@ static void window_ride_colour_dropdown()
window_invalidate(w);
break;
case WIDX_TRACK_MAIN_COLOUR:
game_do_command(0, (0 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, *((uint16*)&w->var_494), 0);
game_do_command(0, (0 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, *((uint16*)&w->var_494), 0);
break;
case WIDX_TRACK_ADDITIONAL_COLOUR:
game_do_command(0, (1 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, *((uint16*)&w->var_494), 0);
game_do_command(0, (1 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, *((uint16*)&w->var_494), 0);
break;
case WIDX_TRACK_SUPPORT_COLOUR:
game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, *((uint16*)&w->var_494), 0);
game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, *((uint16*)&w->var_494), 0);
break;
case WIDX_MAZE_STYLE_DROPDOWN:
game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, *((uint16*)&w->var_494), 0);
game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, *((uint16*)&w->var_494), 0);
break;
case WIDX_ENTRANCE_STYLE_DROPDOWN:
game_do_command(0, (6 << 8) | 1, 0, (window_ride_entrance_style_list[dropdownIndex] << 8) | w->number, GAME_COMMAND_0, 0, 0);
game_do_command(0, (6 << 8) | 1, 0, (window_ride_entrance_style_list[dropdownIndex] << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0);
break;
case WIDX_VEHICLE_COLOUR_SCHEME_DROPDOWN:
game_do_command(0, (5 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, 0, 0);
game_do_command(0, (5 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0);
w->var_48C = 0;
break;
case WIDX_VEHICLE_COLOUR_INDEX_DROPDOWN:
@ -3831,13 +3831,13 @@ static void window_ride_colour_dropdown()
window_invalidate(w);
break;
case WIDX_VEHICLE_MAIN_COLOUR:
game_do_command(0, (2 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, w->var_48C, 0);
game_do_command(0, (2 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->var_48C, 0);
break;
case WIDX_VEHICLE_ADDITIONAL_COLOUR_1:
game_do_command(0, (3 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, w->var_48C, 0);
game_do_command(0, (3 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->var_48C, 0);
break;
case WIDX_VEHICLE_ADDITIONAL_COLOUR_2:
game_do_command(0, (7 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, w->var_48C, 0);
game_do_command(0, (7 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->var_48C, 0);
break;
}
}

View File

@ -169,7 +169,7 @@ rct_window *window_construction_open()
window_push_others_right(w);
show_gridlines();
RCT2_GLOBAL(0xF44070, uint32) = 0x80000000;
RCT2_GLOBAL(0xF44070, uint32) = MONEY32_UNDEFINED;
RCT2_GLOBAL(0xF440CD, uint8) = 8;
RCT2_GLOBAL(0xF440CE, uint8) = 18;
RCT2_GLOBAL(0xF440CF, uint8) = 4;
@ -307,7 +307,7 @@ void window_construction_mouseup_demolish(rct_window* w){
RCT2_CALLPROC_X(0x6C9BA5, 0, 0, 0, 0, (int)w, 0, 0);
return;
RCT2_GLOBAL(0xF44070, uint32) = 0x80000000;
RCT2_GLOBAL(0xF44070, uint32) = MONEY32_UNDEFINED;
sub_6C9627();
RCT2_GLOBAL(0xF440B8, uint8) = 3;
@ -440,7 +440,7 @@ void window_construction_paint()
short string_y = RCT2_GLOBAL(0x9D7C08, int16_t) + w->y - 23;
if (RCT2_GLOBAL(0xF440A6, uint8_t) != 4) gfx_draw_string_centred(dpi, 1407, string_x, string_y, 0, w);
string_y += 11;
if (RCT2_GLOBAL(0xF44070, uint32_t) != 0x80000000 && !(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32_t) & 0x800))
if (RCT2_GLOBAL(0xF44070, uint32_t) != MONEY32_UNDEFINED && !(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32_t) & 0x800))
gfx_draw_string_centred(dpi, 1408, string_x, string_y, 0, (void*)0xF44070);
}

View File

@ -464,7 +464,7 @@ void window_scenery_open()
window->scenery.hover_counter = 0;
window_push_others_below(window);
RCT2_GLOBAL(0x00F64F0D, uint8) = 0;
RCT2_GLOBAL(0x00F64EB4, uint32) = 0x80000000;
RCT2_GLOBAL(0x00F64EB4, uint32) = MONEY32_UNDEFINED;
RCT2_GLOBAL(0x00F64EC0, uint16) = 0;
window_scenery_is_repaint_scenery_tool_on = 0; // repaint colored scenery tool state
window_scenery_is_build_cluster_tool_on = 0; // build cluster tool state
@ -643,7 +643,7 @@ static void window_scenery_mousedown(int widgetIndex, rct_window* w, rct_widget*
if (widgetIndex >= WIDX_SCENERY_TAB_1 && widgetIndex <= WIDX_SCENERY_TAB_20) {
window_scenery_active_tab_index = widgetIndex - WIDX_SCENERY_TAB_1;
window_invalidate(w);
RCT2_GLOBAL(0x00F64EB4, uint32) = 0x80000000;
RCT2_GLOBAL(0x00F64EB4, uint32) = MONEY32_UNDEFINED;
window_scenery_update_scroll(w);
}
}
@ -817,7 +817,7 @@ void window_scenery_scrollmousedown()
window_scenery_is_repaint_scenery_tool_on &= 0xFE;
sound_play_panned(4, (w->width >> 1) + w->x, 0, 0, 0);
w->scenery.hover_counter = -16;
RCT2_GLOBAL(0x00F64EB4, uint32) = 0x80000000;
RCT2_GLOBAL(0x00F64EB4, uint32) = MONEY32_UNDEFINED;
window_invalidate(w);
}
@ -1057,7 +1057,7 @@ void window_scenery_paint()
price = sceneryEntry->small_scenery.price * 10;
}
if (w->scenery.selected_scenery_id == -1 && RCT2_GLOBAL(0x00F64EB4, uint32) != 0x80000000) {
if (w->scenery.selected_scenery_id == -1 && RCT2_GLOBAL(0x00F64EB4, uint32) != MONEY32_UNDEFINED) {
price = RCT2_GLOBAL(0x00F64EB4, uint32);
}

View File

@ -256,7 +256,7 @@ static void window_sign_mouseup()
1 | ((map_element->type&0x3) << 8),
y,
map_element->base_height | ((map_element->properties.scenerymultiple.type >> 10) << 8),
GAME_COMMAND_44,
GAME_COMMAND_REMOVE_LARGE_SCENERY,
0,
0);
break;

View File

@ -457,7 +457,7 @@ void window_staff_overview_mouseup()
w->var_48C = peep->x;
RCT2_CALLPROC_X(0x0069A512, 0, 0, 0, 0, (int)peep, 0, 0);
remove_peep_from_ride(peep);
invalidate_sprite((rct_sprite*)peep);
sprite_move( 0x8000, peep->y, peep->z, (rct_sprite*)peep);
@ -573,19 +573,18 @@ void window_staff_overview_dropdown()
for (int i = 0; i < 128; i++)
{
RCT2_GLOBAL(0x13B0E72 + ebx + i * 4, uint32) = 0;
RCT2_ADDRESS(0x13B0E72 + (peep->staff_id * 512), uint32)[i] = 0;
}
RCT2_GLOBAL(RCT2_ADDRESS_STAFF_MODE_ARRAY + edi, uint16) &= 0xFD; // bug??
RCT2_ADDRESS(RCT2_ADDRESS_STAFF_MODE_ARRAY, uint8)[peep->staff_id] &= ~2;
window_invalidate(w);
//RCT2_CALLPROC_EBPSAFE(0x006C0C3F);
sub_6C0C3F();
gfx_invalidate_screen();
staff_update_greyed_patrol_areas();
}
else {
if (!tool_set(w, widgetIndex, 22)) {
show_gridlines();
RCT2_GLOBAL(0x009DEA50, sint16) = w->number;
window_invalidate(w);
gfx_invalidate_screen();
}
}
}

View File

@ -1417,7 +1417,7 @@ static void window_top_toolbar_scenery_tool_down(short x, short y, rct_window* w
int cost;
{
int esi = 0, eax = grid_x, ecx = grid_y, edx = parameter_2, ebx = (parameter_1 & 0xFF00) | 1;
cost = game_do_command_p(GAME_COMMAND_50, &eax, &ebx, &ecx, &edx, &esi, &banner_id, &ebp);
cost = game_do_command_p(GAME_COMMAND_PLACE_BANNER, &eax, &ebx, &ecx, &edx, &esi, &banner_id, &ebp);
}
if (cost == MONEY32_UNDEFINED)return;
@ -1609,8 +1609,8 @@ void window_top_toolbar_land_tool_drag(short x, short y)
selection_raise_land(GAME_COMMAND_FLAG_APPLY);
RCT2_GLOBAL(RCT2_ADDRESS_LAND_RAISE_COST, uint32) = 0x80000000;
RCT2_GLOBAL(RCT2_ADDRESS_LAND_LOWER_COST, uint32) = 0x80000000;
RCT2_GLOBAL(RCT2_ADDRESS_LAND_RAISE_COST, uint32) = MONEY32_UNDEFINED;
RCT2_GLOBAL(RCT2_ADDRESS_LAND_LOWER_COST, uint32) = MONEY32_UNDEFINED;
return;
}
@ -1619,8 +1619,8 @@ void window_top_toolbar_land_tool_drag(short x, short y)
selection_lower_land(GAME_COMMAND_FLAG_APPLY);
RCT2_GLOBAL(RCT2_ADDRESS_LAND_RAISE_COST, uint32) = 0x80000000;
RCT2_GLOBAL(RCT2_ADDRESS_LAND_LOWER_COST, uint32) = 0x80000000;
RCT2_GLOBAL(RCT2_ADDRESS_LAND_RAISE_COST, uint32) = MONEY32_UNDEFINED;
RCT2_GLOBAL(RCT2_ADDRESS_LAND_LOWER_COST, uint32) = MONEY32_UNDEFINED;
return;
}
@ -1666,8 +1666,8 @@ void window_top_toolbar_water_tool_drag(short x, short y)
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16),
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, uint16)
);
RCT2_GLOBAL(RCT2_ADDRESS_WATER_RAISE_COST, uint32) = 0x80000000;
RCT2_GLOBAL(RCT2_ADDRESS_WATER_LOWER_COST, uint32) = 0x80000000;
RCT2_GLOBAL(RCT2_ADDRESS_WATER_RAISE_COST, uint32) = MONEY32_UNDEFINED;
RCT2_GLOBAL(RCT2_ADDRESS_WATER_LOWER_COST, uint32) = MONEY32_UNDEFINED;
return;
}
@ -1688,8 +1688,8 @@ void window_top_toolbar_water_tool_drag(short x, short y)
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16),
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, uint16)
);
RCT2_GLOBAL(RCT2_ADDRESS_WATER_RAISE_COST, uint32) = 0x80000000;
RCT2_GLOBAL(RCT2_ADDRESS_WATER_LOWER_COST, uint32) = 0x80000000;
RCT2_GLOBAL(RCT2_ADDRESS_WATER_RAISE_COST, uint32) = MONEY32_UNDEFINED;
RCT2_GLOBAL(RCT2_ADDRESS_WATER_LOWER_COST, uint32) = MONEY32_UNDEFINED;
return;
}

View File

@ -19,6 +19,8 @@
*****************************************************************************/
#include "../addresses.h"
#include "../game.h"
#include "../localisation/localisation.h"
#include "banner.h"
rct_banner *gBanners = (rct_banner*)0x0135A124;
@ -32,3 +34,34 @@ void banner_init() {
gBanners[i].type = BANNER_NULL;
}
}
/* rct2: 0x006BA278
* Creates a new banner and returns the index of the banner
* If the flag GAME_COMMAND_FLAG_APPLY is NOT set then returns
* the first unused index but does NOT mark the banner as created.
* returns 0xFF on failure.
*/
int create_new_banner(uint8 flags){
int banner_index = 0;
for (; banner_index < MAX_BANNERS; banner_index++){
if (gBanners[banner_index].type == BANNER_NULL){
break;
}
}
if (banner_index == MAX_BANNERS){
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_TOO_MANY_BANNERS_IN_GAME;
return BANNER_NULL;
}
if (flags & GAME_COMMAND_FLAG_APPLY){
rct_banner* banner = &gBanners[banner_index];
banner->flags = 0;
banner->type = 0;
banner->string_idx = 778;
banner->colour = 2;
banner->text_colour = 2;
}
return banner_index;
}

View File

@ -44,5 +44,6 @@ enum{
extern rct_banner *gBanners;
void banner_init();
int create_new_banner(uint8 flags);
#endif

View File

@ -345,7 +345,7 @@ void remove_banners_at_element(int x, int y, rct_map_element* mapElement){
if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_PATH)return;
else if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_BANNER)continue;
game_do_command(x, 1, y, mapElement->base_height | mapElement->properties.banner.position << 8, GAME_COMMAND_51, 0, 0);
game_do_command(x, 1, y, mapElement->base_height | mapElement->properties.banner.position << 8, GAME_COMMAND_REMOVE_BANNER, 0, 0);
mapElement--;
}
}

View File

@ -48,5 +48,6 @@ void footpath_provisional_remove();
void footpath_provisional_update();
void footpath_get_coordinates_from_pos(int screenX, int screenY, int *x, int *y, int *direction, rct_map_element **mapElement);
void footpath_bridge_get_info_from_pos(int screenX, int screenY, int *x, int *y, int *direction, rct_map_element **mapElement);
void sub_673883(int x, int y, int z);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -129,6 +129,7 @@ enum {
};
enum {
MAP_ELEMENT_FLAG_5 = (1 << 4),
MAP_ELEMENT_FLAG_BROKEN = (1 << 5),
MAP_ELEMENT_FLAG_LAST_TILE = (1 << 7)
};
@ -272,9 +273,23 @@ int sub_68B044();
rct_map_element *map_element_insert(int x, int y, int z, int flags);
int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, void *clearFunc, uint8 bl);
int map_can_construct_at(int x, int y, int zLow, int zHigh, uint8 bl);
int sub_6BA278(int ebx);
void game_command_remove_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_remove_banner(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_set_scenery_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_set_fence_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_set_large_scenery_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_set_banner_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_clear_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_change_surface_style(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_raise_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_lower_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_raise_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_lower_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_remove_fence(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void game_command_place_banner(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
#define GET_MAP_ELEMENT(x) (&(RCT2_ADDRESS(RCT2_ADDRESS_MAP_ELEMENTS, rct_map_element)[x]))
#define TILE_MAP_ELEMENT_POINTER(x) (RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[x])

View File

@ -48,7 +48,7 @@ void map_animation_create(int type, int x, int y, int z)
{
rct_map_animation *aobj = &gAnimatedObjects[0];
int numAnimatedObjects = RCT2_GLOBAL(0x0138B580, uint16);
for (; numAnimatedObjects > 0; aobj++) {
for (int i = 0; i < numAnimatedObjects; i++, aobj++) {
if (aobj->x != x)
continue;
if (aobj->y != y)

View File

@ -178,7 +178,7 @@ void scenery_remove_ghost_tool_placement(){
105 | (RCT2_GLOBAL(0x00F64EC0, uint8) << 8),
y,
z,
GAME_COMMAND_44,
GAME_COMMAND_REMOVE_LARGE_SCENERY,
0,
0);
}
@ -191,7 +191,7 @@ void scenery_remove_ghost_tool_placement(){
105,
y,
z | (RCT2_GLOBAL(0x00F64EC0, uint8) << 8),
GAME_COMMAND_51,
GAME_COMMAND_REMOVE_BANNER,
0,
0);
}

View File

@ -56,14 +56,27 @@ typedef enum {
SMALL_SCENERY_FLAG18 = (1 << 17), // 0x20000
SMALL_SCENERY_FLAG19 = (1 << 18), // 0x40000
SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR = (1 << 19), // 0x80000
SMALL_SCENERY_FLAG20 = (1 << 20), // 0x100000
SMALL_SCENERY_FLAG21 = (1 << 21), // 0x200000
SMALL_SCENERY_FLAG22 = (1 << 22), // 0x400000
SMALL_SCENERY_FLAG23 = (1 << 23), // 0x800000
SMALL_SCENERY_FLAG24 = (1 << 24), // 0x1000000
SMALL_SCENERY_FLAG25 = (1 << 25), // 0x2000000
} SMALL_SCENERY_FLAGS;
typedef struct {
sint16 x_offset;
sint16 y_offset;
sint16 z_offset;
uint8 pad_6[3];
} rct_large_scenery_tile;
typedef struct {
uint8 tool_id; // 0x06
uint8 flags; // 0x07
sint16 price; // 0x08
sint16 removal_price; // 0x0A
uint32 var_0C;
rct_large_scenery_tile* tiles; // 0x0C
uint8 scenery_tab_id; // 0x10
uint8 var_11;
uint32 var_12;