summaryrefslogtreecommitdiff
path: root/reverse-engineering
diff options
context:
space:
mode:
authorlpouzenc <lpouzenc@gmail.com>2013-09-07 19:19:32 +0200
committerlpouzenc <lpouzenc@gmail.com>2013-09-07 19:19:32 +0200
commite36d15da613aae1a0bd6245b8cc23c3ac5ebf95f (patch)
tree1440340d50d8703a261fd0b327c299f1dca35f63 /reverse-engineering
parentc1ccc2a10bbe759ec3e2b6fc3243b58a623d0e16 (diff)
downloadmplemmings-e36d15da613aae1a0bd6245b8cc23c3ac5ebf95f.tar.gz
mplemmings-e36d15da613aae1a0bd6245b8cc23c3ac5ebf95f.tar.bz2
mplemmings-e36d15da613aae1a0bd6245b8cc23c3ac5ebf95f.zip
Tout le reverse est regroupe a present. Manque le makefile car .gitignore un peu violent
Diffstat (limited to 'reverse-engineering')
-rw-r--r--reverse-engineering/dosbox_snif/dos_lemm.h132
-rw-r--r--reverse-engineering/dosbox_snif/int16todec.c9
-rw-r--r--reverse-engineering/dosbox_snif/main_dump.c39
-rw-r--r--reverse-engineering/dosbox_snif/main_dump_delta.c182
-rw-r--r--reverse-engineering/dosbox_snif/main_dump_ds0.c61
-rw-r--r--reverse-engineering/dosbox_snif/main_poke.c64
-rw-r--r--reverse-engineering/dosbox_snif/main_validate_code.c12
-rw-r--r--reverse-engineering/dosbox_snif/rsp.c243
-rw-r--r--reverse-engineering/dosbox_snif/rsp.h27
-rw-r--r--reverse-engineering/dosbox_snif/rsp_lemm.c65
-rw-r--r--reverse-engineering/dosbox_snif/rsp_lemm.h13
-rw-r--r--reverse-engineering/dosbox_snif/utils.c112
-rw-r--r--reverse-engineering/dosbox_snif/utils.h11
-rw-r--r--reverse-engineering/work/seg_code_0208.txt30
14 files changed, 985 insertions, 15 deletions
diff --git a/reverse-engineering/dosbox_snif/dos_lemm.h b/reverse-engineering/dosbox_snif/dos_lemm.h
new file mode 100644
index 0000000..f6c7c95
--- /dev/null
+++ b/reverse-engineering/dosbox_snif/dos_lemm.h
@@ -0,0 +1,132 @@
+#ifndef _DOS_LEMM_H
+#define _DOS_LEMM_H
+
+
+struct _state {
+ uint8_t s_splatting:1; //0x01
+ uint8_t s_exploding:1; //0x02 combinable
+ uint8_t s_falling:1; //0x04
+ uint8_t s_ascending:1; //0x08
+ uint8_t s_digging:1; //0x10
+ uint8_t s_climbing:1; //0x20
+ uint8_t s_climb_ending:1; //0x40
+ uint8_t s_building:1; //0x80
+
+ uint8_t s_blocking:1; //0x01
+ uint8_t s_bashing:1; //0x02
+ uint8_t s_floating:1; //0x04
+ uint8_t s_mining:1; //0x08
+ uint8_t s_drawning:1; //0x10
+ uint8_t s_ending:1; //0x20
+ uint8_t s_dying:1; //0x40
+ uint8_t s_exploding2:1; //0x80
+} __attribute__ ((__packed__));
+
+union state {
+ uint16_t raw;
+ struct _state bits;
+};
+
+enum state_masks {
+ s_splatting = 0x01,
+ s_exploding = 0x02,
+ s_falling = 0x04,
+ s_ascending = 0x08,
+ s_digging = 0x10,
+ s_climbing = 0x20,
+ s_climb_ending = 0x40,
+ s_building = 0x80,
+
+ s_blocking = 0x0100,
+ s_bashing = 0x0200,
+ s_floating = 0x0400,
+ s_mining = 0x0800,
+ s_drawning = 0x1000,
+ s_ending = 0x2000,
+ s_dying = 0x4000,
+ s_exploding2 = 0x8000
+};
+
+struct _flags1 {
+ uint8_t fl1_cap_climber:1; // 0x01
+ uint8_t fl1_unused:6;
+ uint8_t fl1_walk_pause_for_shruggling:1; // 0x80
+} __attribute__ ((__packed__));
+
+union flags1 {
+ uint8_t raw;
+ struct _flags1 bits;
+};
+
+enum flags1_masks {
+ fl1_cap_climber = 0x01;
+ fl1_walk_pause_for_shruggling = 0x80;
+}
+
+struct _lemm_data {
+ /* First lemm is at ds:si == 0b55:0085 */
+ uint16_t x_effective; //0x0 - 0x1
+ uint16_t y_effective; //0x2 - 0x3
+ int16_t x_spr_offset; //0x4 - 0x5
+ int16_t y_spr_offset; //0x6 - 0x7
+ union state state; //0x8 - 0x9
+ uint8_t b_10,b_11;
+ uint16_t spr_data_ptr; //0xc - 0xd
+ uint8_t floattime_dble; //0xe
+ uint8_t b_15,b_16,b_17,b_18,b_19;
+ uint16_t ptr2; //0x14 - 0x15
+ uint8_t b_22,b_23,b_24,b_25,b_26,b_27,b_28,b_29,b_30,b_31;
+ uint8_t expl_countdown; //0x20
+ uint8_t steps_remain; //0x21
+ uint8_t b_34;
+ uint8_t falldist; //0x23
+ union flags1 flags1; //0x24
+ uint8_t cap_floater; //0x25
+ uint8_t is_gone; //0x26
+ int8_t direction; //0x27
+ uint8_t spr_frame; //0x28
+ uint8_t draw_hint; //0x29
+ uint8_t b_42,b_43,b_44;
+} __attribute__ ((__packed__));
+
+union lemm_data {
+ unsigned char raw[0x2d];
+ struct _lemm_data s;
+};
+
+enum draw_hint {
+ hint_nothing=0x00, hint_falling=0x04, hint_special1=0x08, /* climbing or slow falling or shruggling */
+ hint_walking=0x09, hint_building=0x10, hint_mining=0x18, hint_bashing=0x20
+};
+
+struct _avail_skills {
+ uint8 sk_climber, sk_climber2, sk_climber_tag; // [0x67]
+ uint8 sk_floater, sk_floater2, sk_floater_tag; // [0x6a]
+ uint8 sk_bomber, sk_bomber2, sk_bomber_tag; // [0x6d]
+ uint8 sk_blocker, sk_blocker2, sk_blocker_tag; // [0x70]
+ uint8 sk_builder, sk_builder2, sk_builder_tag; // [0x73]
+ uint8 sk_basher, sk_basher2, sk_basher_tag; // [0x76]
+ uint8 sk_miner, sk_miner2, sk_miner_tag; // [0x79]
+ uint8 sk_digger, sk_digger2, sk_digger_tag; // [0x7c]
+} __attribute__ ((__packed__));
+
+struct game_data {
+ /* ds == 0x0b55 */
+ uint8 unk1[0x27]; // TODO
+ uint8 paused; // [0x28]
+ uint8 unk2[0x10]; // TODO
+ uint8 lemm_count_to_process; // [0x39]
+ uint8 lemm_spawned_count; // [0x40]
+ uint8 unk3; // TODO
+ uint8 lemm_out_count; // [0x42]
+ uint8 unk4; // TODO
+ uint8 lemm_level_count; // [0x44]
+ uint8 next_spawn_ticks; // [0x45]
+ uint8 spawn_rate_ticks; // [0x46]
+ uint8 unk5[0x20]; // TODO
+ struct _avail_skills avail_skills; // [0x67] - [0x7e]
+ uint8 unk6[0x06]; // TODO
+ struct _lemm_data lemmings[100]; // [0x85]
+} __attribute__ ((__packed__));
+
+#endif /*_DOS_LEMM_H*/
diff --git a/reverse-engineering/dosbox_snif/int16todec.c b/reverse-engineering/dosbox_snif/int16todec.c
new file mode 100644
index 0000000..6499bf6
--- /dev/null
+++ b/reverse-engineering/dosbox_snif/int16todec.c
@@ -0,0 +1,9 @@
+#include <stdint.h>
+#include <stdio.h>
+
+int main() {
+ int16_t i;
+ scanf("%x", &i);
+ printf("0x%04x => %i\n", i, i);
+ return 0;
+}
diff --git a/reverse-engineering/dosbox_snif/main_dump.c b/reverse-engineering/dosbox_snif/main_dump.c
new file mode 100644
index 0000000..68bd4c0
--- /dev/null
+++ b/reverse-engineering/dosbox_snif/main_dump.c
@@ -0,0 +1,39 @@
+#include "rsp.h"
+#include "rsp_lemm.h"
+#include "utils.h"
+
+#include <string.h> /* memset() */
+#include <stdio.h> /* printf() */
+
+int main(int argc, char *argv[]) {
+ int rv, end=0;
+ struct rsp_state rsp;
+ char ds_si[10], command[16];
+
+ rv=rsp_lemm_init(&rsp, ds_si);
+ if ( rv != 0 ) {
+ printf("Error rsp_lemm_init() returns %i\n", rv);
+ return 1;
+ }
+
+ while (!end) {
+ rsp_query(&rsp, "c"); // Continue
+ if ( rsp.replied != 1 ) printf("Bug 03\n");
+ rsp_recv_full(&rsp);
+ if ( rsp_check_and_clear(&rsp, "S05") != 0 ) printf("Bug 04\n");
+
+ snprintf(command, 15, "m%s,0x2d", ds_si);
+ rsp_query(&rsp, command); // Read a lemming record
+ if ( rsp_decode(&rsp) != 0x2d * 2 ) {
+ printf("Bug 07\n");
+ } else {
+ printf("%s\n", rsp.decoded);
+ }
+ }
+
+
+ rsp_quit(&rsp);
+ return 0;
+}
+
+
diff --git a/reverse-engineering/dosbox_snif/main_dump_delta.c b/reverse-engineering/dosbox_snif/main_dump_delta.c
new file mode 100644
index 0000000..8db3671
--- /dev/null
+++ b/reverse-engineering/dosbox_snif/main_dump_delta.c
@@ -0,0 +1,182 @@
+#include "rsp.h"
+#include "rsp_lemm.h"
+#include "utils.h"
+#include "dos_lemm.h"
+
+#include <stdint.h> /* uint16_t... */
+#include <string.h> /* strcpy() */
+#include <stdio.h> /* printf() */
+
+
+int main(int argc, char *argv[]) {
+ int i, rv, similar_frames, end;
+ struct rsp_state rsp;
+ char ds_si[10], command[16];
+ union lemm_data lemm, prevlemm;
+ char draw_hint_str[256][16];
+ char state_str[16][16];
+
+ memset(lemm.raw, 0, sizeof(lemm.raw));
+
+ for (i=0;i<256;i++) strcpy(draw_hint_str[i], "hint_unknown");
+ strcpy(draw_hint_str[hint_nothing], "hint_nothing");
+ strcpy(draw_hint_str[hint_falling], "hint_falling");
+ strcpy(draw_hint_str[hint_special1],"hint_special1");
+ strcpy(draw_hint_str[hint_walking], "hint_walking");
+ strcpy(draw_hint_str[hint_building],"hint_building");
+ strcpy(draw_hint_str[hint_mining], "hint_mining");
+ strcpy(draw_hint_str[hint_bashing], "hint_bashing");
+
+ strcpy(state_str[s_splatting],"s_splatting");
+ strcpy(state_str[s_exploding],"s_exploding");
+ strcpy(state_str[s_falling],"s_falling");
+ strcpy(state_str[s_ascending],"s_ascending");
+ strcpy(state_str[s_digging],"s_digging");
+ strcpy(state_str[s_climbing],"s_climbing");
+ strcpy(state_str[s_climb_ending],"s_climb_ending");
+ strcpy(state_str[s_building],"s_building");
+ strcpy(state_str[s_blocking],"s_blocking");
+ strcpy(state_str[s_bashing],"s_bashing");
+ strcpy(state_str[s_floating],"s_floating");
+ strcpy(state_str[s_mining],"s_mining");
+ strcpy(state_str[s_drawning],"s_drawning");
+ strcpy(state_str[s_ending],"s_ending");
+ strcpy(state_str[s_dying],"s_dying");
+ strcpy(state_str[s_exploding2],"s_exploding2");
+
+ rv=rsp_lemm_init(&rsp, ds_si);
+ if ( rv != 0 ) {
+ printf("Error rsp_lemm_init() returns %i\n", rv);
+ return 1;
+ }
+
+ end=0;
+ similar_frames=0;
+ while (!end) {
+ rsp_query(&rsp, "c"); // Continue
+ if ( rsp.replied != 1 ) printf("Bug 03\n");
+ rsp_recv_full(&rsp);
+ if ( rsp_check_and_clear(&rsp, "S05") != 0 ) printf("Bug 04\n");
+
+ snprintf(command, 15, "m%s,0x2d", ds_si);
+ rsp_query(&rsp, command); // Read a lemming record
+ if ( rsp_decode(&rsp) != 2*sizeof(lemm.raw) ) {
+ printf("Bug 07\n");
+ continue;
+ }
+
+ memcpy(prevlemm.raw, lemm.raw, sizeof(lemm.raw));
+
+ //printf("%s\n", rsp.decoded);
+ rv = hexascii2bin(rsp.decoded, lemm.raw, sizeof(lemm.raw));
+ if ( rv != sizeof(lemm.raw) ) {
+ printf("Bug 08\n");
+ continue;
+ }
+
+ for (i=0; i<sizeof(lemm.raw); i++) {
+ // Search the differences between previous frame and now
+ if ( prevlemm.raw[i] == lemm.raw[i] ) continue;
+
+ switch(i) {
+ case 0x0: // x
+ case 0x1: // x
+ case 0x2: // y
+ case 0x3: // y
+ case 0x28: //spr_frame
+ continue; // Don't want to see those state changes because is well-known and frequent
+ case 0x20: //expl_countdown
+ if ( lemm.s.expl_countdown < 0x4e && lemm.s.expl_countdown > 0x02) {
+ // Skip detailing all 80 changes... Just beginning and ending
+ continue;
+ }
+ }
+
+ // If here, an interessting change has been detected
+ if ( similar_frames > 0) {
+ printf("(%i similar frames)\n", similar_frames);
+ }
+ similar_frames=-1;
+
+ switch(i) {
+
+ case 0x4: // x_spr_offset
+ i=0x5; // go to the next case (prevents double printing)
+ case 0x5: // x_spr_offset
+ printf("x_spr_offset\t%i -> %i\n",prevlemm.s.x_spr_offset, lemm.s.x_spr_offset);
+ break;
+ case 0x6: // y_spr_offset
+ i=0x7;
+ case 0x7: // y_spr_offset
+ printf("y_spr_offset\t%i -> %i\n",prevlemm.s.y_spr_offset, lemm.s.y_spr_offset);
+ break;
+ case 0x8: // state
+ i=0x9;
+ case 0x9: // state
+ rv=bit_position(lemm.s.state.raw);
+ switch (rv) {
+ case -2:
+ //FIXME : boucle bit par bit car ya parfois de multiple bits...
+ printf("state\t\t%04x -> %04x (multiple)\n",prevlemm.s.state.raw, lemm.s.state.raw);
+ break;
+ case -1:
+ printf("state\t\t%04x -> %04x (walking...)\n",prevlemm.s.state.raw, lemm.s.state.raw);
+ break;
+ default:
+ printf("state\t\t%04x -> %04x (%s)\n",prevlemm.s.state.raw, lemm.s.state.raw, state_str[rv]);
+ break;
+ }
+ break;
+ case 0xc: // spr_data_ptr
+ i=0xd;
+ case 0xd: // spr_data_ptr
+ printf("spr_data_ptr\t%04x -> %04x\n",prevlemm.s.spr_data_ptr, lemm.s.spr_data_ptr);
+ break;
+ case 0xe: // floattime_dble ?
+ printf("floattime_dble\t%02x -> %02x\n",prevlemm.s.floattime_dble, lemm.s.floattime_dble);
+ break;
+ case 0x14: // ptr2 ?
+ i=0x15;
+ case 0x15: // ptr2 ?
+ printf("ptr2\t\t%04x -> %04x\n",prevlemm.s.ptr2, lemm.s.ptr2);
+ break;
+ case 0x20: //expl_countdown
+ printf("expl_countdown\t%02x -> %02x\n",prevlemm.s.expl_countdown, lemm.s.expl_countdown);
+ break;
+ case 0x21: //steps_remain
+ printf("steps_remain\t%02x -> %02x\n",prevlemm.s.steps_remain, lemm.s.steps_remain);
+ break;
+ case 0x23: //falldist
+ printf("falldist\t%02x -> %02x\n",prevlemm.s.falldist, lemm.s.falldist);
+ break;
+ case 0x24: //flags1
+ if ( prevlemm.s.flags1.bf.cap_climber != lemm.s.flags1.bf.cap_climber ) {
+ printf("cap_climber\t%2i -> %2i\n", prevlemm.s.flags1.bf.cap_climber, lemm.s.flags1.bf.cap_climber);
+ } else if ( prevlemm.s.flags1.bf.walk_pause_for_shruggling != lemm.s.flags1.bf.walk_pause_for_shruggling ) {
+ printf("walk_pause_for_shruggling\t%2i -> %2i\n", prevlemm.s.flags1.bf.walk_pause_for_shruggling, lemm.s.flags1.bf.walk_pause_for_shruggling);
+ } else {
+ printf("flags1.unknown\t%02x -> %02x\n",prevlemm.s.flags1.raw, lemm.s.flags1.raw);
+ }
+ break;
+ case 0x25: //cap_floater
+ printf("cap_floater\t%02x -> %02x\n",prevlemm.s.cap_floater, lemm.s.cap_floater);
+ break;
+ case 0x26: //is_gone
+ printf("is_gone\t%02x -> %02x\n",prevlemm.s.is_gone, lemm.s.is_gone);
+ break;
+ case 0x27: //direction
+ printf("direction\t%i -> %i\n",prevlemm.s.direction, lemm.s.direction);
+ break;
+ case 0x29: //draw_hint ?
+ printf("draw_hint\t\t%02x -> %02x (%s)\n",prevlemm.s.draw_hint, lemm.s.draw_hint, draw_hint_str[lemm.s.draw_hint]);
+ break;
+ default:
+ printf("(0x%02x)\t\t%02x -> %02x\n", i, prevlemm.raw[i], lemm.raw[i]);
+ }
+ }
+ similar_frames++;
+ }
+ rsp_quit(&rsp);
+ return 0;
+}
+
diff --git a/reverse-engineering/dosbox_snif/main_dump_ds0.c b/reverse-engineering/dosbox_snif/main_dump_ds0.c
new file mode 100644
index 0000000..e54589d
--- /dev/null
+++ b/reverse-engineering/dosbox_snif/main_dump_ds0.c
@@ -0,0 +1,61 @@
+#include "rsp.h"
+#include "rsp_lemm.h"
+#include "utils.h"
+
+#include <string.h> /* memset() */
+#include <stdio.h> /* printf() */
+
+int main(int argc, char *argv[]) {
+ int rv, i, end=0;
+ struct rsp_state rsp;
+ char ds_si[10], command[16];
+ unsigned int addr, ds_offset;
+
+ rv=rsp_lemm_init(&rsp, ds_si);
+ if ( rv != 0 ) {
+ printf("Error rsp_lemm_init() returns %i\n", rv);
+ return 1;
+ }
+
+ while (!end) {
+ rsp_query(&rsp, "c"); // Continue
+ if ( rsp.replied != 1 ) printf("Bug 03\n");
+ rsp_recv_full(&rsp);
+ if ( rsp_check_and_clear(&rsp, "S05") != 0 ) printf("Bug 04\n");
+
+ // For the beginning of the ds segment
+ ds_offset=0;
+ /* For this chunk of code :
+ 000052A3 83E307 and bx,byte +0x7 bx = 0x5660 + lemm.x_effective % 8;
+ 000052A6 81C36056 add bx,0x5660 //
+ 000052AA 8A27 mov ah,[bx] ah = [bx];
+ */
+ ds_offset = 0x5660;
+ /* For understanding pixel collision tests at 00005280
+ di = lemm.y_effective - 16;
+ if ( di >= 0 ) di=0; //WTF ???
+ di *= (LEVEL_WIDTH/8);
+ di += 0x6d60 + lemm.x_effective / 8;
+ */
+ ds_offset = 0x6d60;
+
+ ds_offset = 0x3f;
+ for (i=0;i<8;i++) {
+ addr = (0xb55 << 4) + ds_offset + (i * 0x20);
+ snprintf(command, 15, "m%06x,0x20", addr );
+ rsp_query(&rsp, command);
+ if ( rsp_decode(&rsp) != 0x20 *2) {
+ printf("%06x : Bug\n", addr);
+ } else {
+ printf("%06x : %s\n", addr, rsp.decoded);
+ }
+ }
+ printf("\n");
+ }
+
+
+ rsp_quit(&rsp);
+ return 0;
+}
+
+
diff --git a/reverse-engineering/dosbox_snif/main_poke.c b/reverse-engineering/dosbox_snif/main_poke.c
new file mode 100644
index 0000000..e0048fa
--- /dev/null
+++ b/reverse-engineering/dosbox_snif/main_poke.c
@@ -0,0 +1,64 @@
+#include "rsp.h"
+#include "rsp_lemm.h"
+#include "utils.h"
+
+#include <string.h> /* memset() */
+#include <stdio.h> /* printf() */
+
+int main(int argc, char *argv[]) {
+ int rv, i, end_input, end_loop;
+ struct rsp_state rsp;
+ char ds_si[10], command[16], input[100];
+ unsigned int poke_base, poke_off, poke_val;
+
+ rv=rsp_lemm_init(&rsp, ds_si);
+ if ( rv != 0 ) {
+ printf("Error rsp_lemm_init() returns %i\n", rv);
+ return 1;
+ }
+ if ( sscanf(ds_si, "%x", &poke_base) != 1 ) printf("Bug 20\n");;
+
+ end_loop=0;
+ while (!end_loop) {
+ rsp_query(&rsp, "c"); // Continue
+ if ( rsp.replied != 1 ) printf("Bug 03\n");
+ rsp_recv_full(&rsp);
+ if ( rsp_check_and_clear(&rsp, "S05") != 0 ) printf("Bug 04\n");
+
+ snprintf(command, 15, "m%s,0x2d", ds_si);
+ rsp_query(&rsp, command); // Read a lemming record
+ if ( rsp_decode(&rsp) != 0x2d * 2 ) {
+ printf("Bug 07\n");
+ } else {
+ for (i=0; rsp.decoded[i]!='\0'; i++) {
+ putchar(rsp.decoded[i]);
+ if (i%2==1) putchar(' ');
+ if (i%16==15) putchar(' ');
+ }
+ putchar('\n');
+ }
+
+ end_input=0;
+ do {
+ printf("address value ? "); fflush(stdout);
+ if ( fgets(input, 99, stdin) == NULL ) {
+ //printf("pb fgets\n");
+ end_input=1; continue;
+ }
+ if ( sscanf(input,"%x %x", &poke_off, &poke_val) != 2 ) {
+ //printf("pb sscanf\n");
+ end_input=1; continue;
+ }
+ if ( rsp_poke(&rsp, poke_base + poke_off, poke_val) != 0 ) {
+ printf("Bug 21\n");
+ end_input=1; continue;
+ }
+ } while ( !end_input );
+ }
+
+
+ rsp_quit(&rsp);
+ return 0;
+}
+
+
diff --git a/reverse-engineering/dosbox_snif/main_validate_code.c b/reverse-engineering/dosbox_snif/main_validate_code.c
new file mode 100644
index 0000000..a016a54
--- /dev/null
+++ b/reverse-engineering/dosbox_snif/main_validate_code.c
@@ -0,0 +1,12 @@
+#include "dos_lemm.h"
+
+int main() {
+ struct game_data g;
+ struct _lemm_data *lemm;
+
+ lemm = g.lemmings;
+ lemm->draw_hint = hint_walking;
+
+ return lemm->draw_hint;
+}
+
diff --git a/reverse-engineering/dosbox_snif/rsp.c b/reverse-engineering/dosbox_snif/rsp.c
new file mode 100644
index 0000000..c9957b7
--- /dev/null
+++ b/reverse-engineering/dosbox_snif/rsp.c
@@ -0,0 +1,243 @@
+#include "rsp.h"
+
+/* recv() */
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <string.h> /* memset(), strncmp() */
+#include <stdio.h> /* perror(), fprintf(), snprintf(), sscanf() */
+#include <stdlib.h> /* malloc(), free() */
+#include <unistd.h> /* close() */
+#include <errno.h> /* EAGAIN... */
+
+void _rsp_sniff_garbage(struct rsp_state *rsp) {
+ int recvbytes, rv;
+
+ // Sniff garbages before sending command
+ recvbytes = recv(rsp->sockfd, rsp->response, rsp->data_maxlen, MSG_DONTWAIT);
+ if ( recvbytes < 0 ) {
+ rv = errno;
+ if ( rv == EAGAIN || rv == EWOULDBLOCK ) {
+ /* No garbage found, that's a good news */
+ } else {
+ LOG_DEBUG("! <-(error %i)\n", rv);
+ }
+ recvbytes=0;
+ }
+ rsp->response[recvbytes] = '\0';
+ if ( recvbytes > 0 ) {
+ LOG_DEBUG("! <-'%s'\n",rsp->response);
+ }
+}
+
+int rsp_recv_full(struct rsp_state *rsp) {
+
+ int rv, error=0, complete=0, full=0, sentbytes;
+ ssize_t bufoldpos=0, bufpos=0;
+ char *bom=NULL, *eom=NULL, *ptr;
+ unsigned char c, cack='+';
+ unsigned int computed_checksum, read_checksum;
+
+ do {
+ rv = recv(rsp->sockfd, rsp->response + bufpos, rsp->data_maxlen - bufpos, 0);
+ if ( rv < 0 ) {
+ switch (errno) {
+ case EAGAIN:
+ continue;
+ default:
+ error=1;
+ continue;
+ }
+ }
+ if ( rv == 0 ) {
+ error=1;
+ continue;
+ }
+
+ bufoldpos = bufpos;
+ bufpos += rv;
+
+ if ( bom == NULL ) {
+ bom = memchr(rsp->response + bufoldpos, '$', bufpos - bufoldpos);
+ }
+
+ if ( bom != NULL && eom == NULL ) {
+ eom = memchr(bom, '#', bufpos - (bom - rsp->response) );
+ }
+
+ complete = bom && eom && (eom+2) <= (rsp->response + bufpos); // 2 char checksum after EOM
+ full = (bufpos >= rsp->data_maxlen);
+
+ } while (!error && !complete && !full);
+
+ if (error) return 1;
+ if (full) return 2;
+
+ rsp->response[bufpos]='\0';
+
+ c=eom[3];
+ eom[3]='\0';
+ LOG_DEBUG(" <- '%s'\n", rsp->response);
+
+ if ( (eom+3) < (rsp->response + bufpos - 1)) {
+ eom[3]=c;
+ LOG_DEBUG("? <- '%s'\n", eom+3);
+ }
+
+
+ rsp->response_len = eom - bom - 1;
+ rsp->response_bom = bom;
+ rsp->response_eom = eom;
+
+ computed_checksum=0;
+ for (ptr = bom+1; ptr < eom; ptr++) {
+ computed_checksum = (computed_checksum + ((unsigned char)*ptr) ) % 256;
+ }
+
+ rv = sscanf(eom + 1, "%02x", &read_checksum);
+ if ( rv != 1 || computed_checksum != read_checksum) return 3;
+
+ rsp->replied = 1;
+
+ if (rsp->noackmode !=1) {
+ sentbytes = send(rsp->sockfd, &cack, 1, 0);
+ if ( sentbytes < 1 ) return 4;
+ LOG_DEBUG("-> '+'\n");
+ }
+
+ return 0;
+}
+
+int rsp_init(int sockfd, int data_maxlen, struct rsp_state *rsp) {
+ memset(rsp,0,sizeof(struct rsp_state));
+ rsp->sockfd = sockfd;
+ rsp->data_maxlen = data_maxlen;
+
+ rsp->command = malloc(data_maxlen+1);
+ if ( rsp->command == NULL ) return 1;
+
+ rsp->response = malloc(data_maxlen+1);
+ if ( rsp->response == NULL ) return 1;
+
+ rsp->decoded = malloc(data_maxlen+1);
+ if ( rsp->decoded == NULL ) return 1;
+
+/*
+ rsp_query(rsp, "QStartNoAckMode");
+ if ( rsp_check_and_clear(rsp, "OK") == 0 ) rsp->noackmode=1;
+*/
+ return 0;
+}
+
+void rsp_quit(struct rsp_state *rsp) {
+ //rsp_query(rsp, "k");
+ if ( rsp->command != NULL ) free(rsp->command);
+ if ( rsp->response != NULL ) free(rsp->response);
+ if ( rsp->decoded != NULL ) free(rsp->decoded);
+ close(rsp->sockfd);
+ memset(rsp,0,sizeof(struct rsp_state));
+}
+
+void rsp_send_break(struct rsp_state *rsp) {
+ int sentbytes;
+ char cbreak=3;
+
+ rsp->replied = 0;
+ rsp->response_len = 0;
+
+ _rsp_sniff_garbage(rsp);
+
+ sentbytes = send(rsp->sockfd, &cbreak, 1, 0);
+ if ( sentbytes < 1 ) return;
+ LOG_DEBUG("-> '^C'\n");
+
+ rsp_recv_full(rsp);
+}
+
+void rsp_query(struct rsp_state *rsp, char command[]) {
+ int sentbytes;
+ unsigned int checksum, i;
+ unsigned char c;
+
+
+ rsp->replied = 0;
+ rsp->response_len = 0;
+
+ i=0; checksum=0;
+ while ( (c=command[i++]) != '\0' ) {
+ checksum = (checksum + c ) % 256;
+ }
+
+ rsp->command_len = snprintf(rsp->command, rsp->data_maxlen, "$%s#%02x", command, checksum);
+ if (rsp->command_len < 5) return;
+
+ _rsp_sniff_garbage(rsp);
+
+ sentbytes = send(rsp->sockfd, rsp->command, rsp->command_len, 0);
+ if ( sentbytes < rsp->command_len ) return;
+ LOG_DEBUG("-> '%s'\n", rsp->command);
+
+
+ rsp_recv_full(rsp);
+}
+
+int rsp_check_and_clear(struct rsp_state *rsp, char expected_response[]) {
+
+ int expected_responselen = strlen(expected_response);
+
+ if ( rsp->replied != 1 ) return 1;
+ rsp->replied = 0;
+
+ if ( rsp->response_len < expected_responselen ) return 2;
+ if ( strncmp(rsp->response_bom + 1, expected_response, expected_responselen) != 0 ) return 3;
+
+ return 0;
+}
+
+int rsp_decode(struct rsp_state *rsp) {
+/*
+Response data can be run-length encoded to save space. Run-length encoding replaces runs of identical characters with one instance of the repeated character, followed by a ‘*’ and a repeat count. The repeat count is itself sent encoded, to avoid binary characters in data: a value of n is sent as n+29. For a repeat count greater or equal to 3, this produces a printable ascii character, e.g. a space (ascii code 32) for a repeat count of 3. (This is because run-length encoding starts to win for counts 3 or more.) Thus, for example, ‘0* ’ is a run-length encoding of “0000”: the space character after ‘*’ means repeat the leading 0 32 - 29 = 3 more times.
+
+The printable characters ‘#’ and ‘$’ or with a numeric value greater than 126 must not be used. Runs of six repeats (‘#’) or seven repeats (‘$’) can be expanded using a repeat count of only five (‘"’). For example, ‘00000000’ can be encoded as ‘0*"00’.
+*/
+ char src, *srcptr, *dstptr;
+ int repe, max;
+
+ if ( rsp->replied != 1 ) return -1;
+
+ dstptr = rsp->decoded;
+ for ( srcptr = rsp->response_bom+1; srcptr < rsp->response_eom; srcptr++ ) {
+ // FIXME : implemnt RLE decoding
+ src = *srcptr;
+ switch (src) {
+ case '*':
+ srcptr++;
+ repe=(*srcptr)-29;
+ if (repe < 2 ) return -1;
+ max = rsp->decoded + rsp->data_maxlen - 1 - dstptr;
+ if ( repe > max ) { repe = max; }
+ memset(dstptr, *(srcptr-2), repe);
+ dstptr += repe;
+ break;
+ default:
+ *(dstptr++) = *srcptr;
+ break;
+ }
+ }
+ *dstptr='\0';
+
+ return dstptr - rsp->decoded;
+}
+
+int rsp_poke(struct rsp_state *rsp, unsigned int poke_addr, unsigned int poke_value) {
+ char command[16];
+ printf("DEBUG : rsp_poke()\n");
+ if ( snprintf(command, 15, "M %4x,2:%2x", poke_addr & 0xffff, poke_value & 0xff) < 11 ) return 1;
+ printf("DEBUG : command == '%s'\n", command);
+ rsp_query(rsp, command); // Send the poke command to GDB stub
+ printf("DEBUG : response == '%s'\n", rsp->response);
+ if ( rsp_check_and_clear(rsp, "OK") != 0 ) return 2;
+
+ return 0;
+}
+
diff --git a/reverse-engineering/dosbox_snif/rsp.h b/reverse-engineering/dosbox_snif/rsp.h
new file mode 100644
index 0000000..c8f1378
--- /dev/null
+++ b/reverse-engineering/dosbox_snif/rsp.h
@@ -0,0 +1,27 @@
+#ifndef _RSP_H
+#define _RSP_H
+
+#define LOG_DEBUG(...)
+//#include <stdio.h>
+//#define LOG_DEBUG(...) printf(__VA_ARGS__)
+
+struct rsp_state {
+ int sockfd;
+ int data_maxlen;
+ int noackmode;
+ int replied;
+ int command_len, response_len;
+ char *command, *response, *decoded; /* Malloc'ed */
+ char *response_bom, *response_eom; /* Just pointers on *response string */
+};
+
+int rsp_init(int sockfd, int data_maxlen, struct rsp_state *rsp);
+void rsp_quit(struct rsp_state *rsp);
+void rsp_send_break(struct rsp_state *rsp);
+void rsp_query(struct rsp_state *rsp, char command[]);
+int rsp_check_and_clear(struct rsp_state *rsp, char expected_response[]);
+int rsp_recv_full(struct rsp_state *rsp);
+int rsp_decode(struct rsp_state *rsp);
+int rsp_poke(struct rsp_state *rsp, unsigned int poke_addr, unsigned int poke_value);
+
+#endif /*_RSP_H*/
diff --git a/reverse-engineering/dosbox_snif/rsp_lemm.c b/reverse-engineering/dosbox_snif/rsp_lemm.c
new file mode 100644
index 0000000..e39ef30
--- /dev/null
+++ b/reverse-engineering/dosbox_snif/rsp_lemm.c
@@ -0,0 +1,65 @@
+#include "rsp_lemm.h"
+#include "utils.h"
+
+#include <string.h> /* memset(), strncmp() */
+#include <stdio.h> /* printf() */
+
+int rsp_lemm_init(struct rsp_state *rsp, char *ds_si) {
+ int rv;
+ int sockfd;
+
+ memset(ds_si,'X',10);
+ ds_si[9]='\0';
+
+ rv = tcp_client_init(HOST, PORT, &sockfd);
+ if ( rv != 0 ) return rv;
+
+ rsp_init(sockfd, MAXDATASIZE-1, rsp);
+
+/*
+ rsp_query(rsp, "qRcmd,666c61745f6569702c30"); //flat_eip,0
+ if ( rsp_check_and_clear(rsp, "OK") != 0 ) printf("Bug\n");
+*/
+ rsp_query(rsp, "?");
+ if ( rsp_check_and_clear(rsp, "S05") != 0 ) {
+ // The program is not stopped
+ rsp_send_break(rsp); // Request to freeze the program
+ if ( rsp->replied != 1 ) return 10;
+ }
+
+ rsp_query(rsp, "Z0,38C4,1"); // Set execution breakpoint at 0208:1844 (0x38C4)
+ if ( rsp_check_and_clear(rsp, "OK") != 0 ) return 11;
+
+ do {
+ rsp_query(rsp, "c"); // Continue
+ if ( rsp->replied != 1 ) continue; //return 12;
+ rsp_recv_full(rsp);
+ if ( rsp_check_and_clear(rsp, "S05") != 0 ) continue; //return 13;
+// (void) rsp_check_and_clear(rsp, "S05");
+
+ rsp_query(rsp, "p8"); // Read $eip (/!\ byte order. ex : $e4b0* !#76 )
+// if ( rsp_check_and_clear(rsp, "c4380000") != 0 ) return 14;
+ } while ( rsp_check_and_clear(rsp, "c4380000") != 0 );
+
+ rsp_query(rsp, "pc"); // Read $ds
+ if ( rsp_decode(rsp) <8 ) return 15;
+ ds_si[0]=rsp->decoded[2];
+ ds_si[1]=rsp->decoded[3];
+ ds_si[2]=rsp->decoded[0];
+ ds_si[3]=rsp->decoded[1];
+ ds_si[4]=':';
+
+ rsp_query(rsp, "p6"); // Read $si
+ if ( rsp_decode(rsp) <8 ) return 16;
+ ds_si[5]=rsp->decoded[2];
+ ds_si[6]=rsp->decoded[3];
+ ds_si[7]=rsp->decoded[0];
+ ds_si[8]=rsp->decoded[1];
+
+ printf("ds:si == %s\n", ds_si);
+ flatten(ds_si);
+ printf("$ds_si == %s\n", ds_si);
+
+ return 0;
+}
+
diff --git a/reverse-engineering/dosbox_snif/rsp_lemm.h b/reverse-engineering/dosbox_snif/rsp_lemm.h
new file mode 100644
index 0000000..bd95d4f
--- /dev/null
+++ b/reverse-engineering/dosbox_snif/rsp_lemm.h
@@ -0,0 +1,13 @@
+#ifndef _RSP_LEMM_H
+#define _RSP_LEMM_H
+
+#include "rsp.h"
+
+#define HOST "localhost"
+#define PORT "1234"
+#define MAXDATASIZE 1400
+
+
+int rsp_lemm_init(struct rsp_state *rsp, char *ds_si);
+
+#endif /*_RSP_LEMM_H*/
diff --git a/reverse-engineering/dosbox_snif/utils.c b/reverse-engineering/dosbox_snif/utils.c
new file mode 100644
index 0000000..8e26d46
--- /dev/null
+++ b/reverse-engineering/dosbox_snif/utils.c
@@ -0,0 +1,112 @@
+#include "utils.h"
+
+/* socket() */
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+/* getaddrinfo() */
+#include <sys/types.h>
+#include <netdb.h>
+/* inet_ntop() */
+#include <arpa/inet.h>
+#define GET_SOCK_IN_ADDR(sa) (((struct sockaddr*)sa)->sa_family == AF_INET)?(void *)&(((struct sockaddr_in*)sa)->sin_addr):(void *)&(((struct sockaddr_in6*)sa)->sin6_addr)
+
+#include <string.h> /* memset(), strncmp() */
+#include <stdio.h> /* perror(), fprintf(), snprintf(), sscanf() */
+#include <stdlib.h> /* malloc(), free() */
+#include <unistd.h> /* close() */
+#include <errno.h> /* EAGAIN... */
+
+
+int tcp_client_init(char host[], char port[], int *sockfd) {
+ int rv, flag=1;
+ char s[INET6_ADDRSTRLEN];
+ struct addrinfo hints, *servinfo, *p;
+ memset(&hints,0,sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ if ((rv = getaddrinfo(host, port, &hints, &servinfo)) != 0) {
+ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
+ return 1;
+ }
+
+
+ // loop through all the results and connect to the first we can
+ for(p = servinfo; p != NULL; p = p->ai_next) {
+ if ((*sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
+ //perror("client: socket");
+ continue;
+ }
+
+ if ( setsockopt(*sockfd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(flag)) != 0 ) {
+ perror("client: setsockopt TCP_NODELAY");
+ }
+
+ if (connect(*sockfd, p->ai_addr, p->ai_addrlen) == -1) {
+ close(*sockfd);
+ //perror("client: connect");
+ continue;
+ }
+
+ break;
+ }
+
+ freeaddrinfo(servinfo);
+
+ if (p == NULL) {
+ fprintf(stderr, "client: failed to connect\n");
+ return 2;
+ }
+
+ inet_ntop(p->ai_family, GET_SOCK_IN_ADDR(p->ai_addr), s, sizeof s);
+ printf("client: connecting to %s\n", s);
+
+ return 0;
+}
+
+void flatten(char *seg_off) {
+ unsigned int seg=0, off=0, flat;
+ sscanf(seg_off, "%4x", &seg);
+ sscanf(seg_off+5, "%4x", &off);
+ flat= (seg<<4) + off;
+ snprintf(seg_off, 9, "%x", flat);
+}
+
+
+int hexascii2bin(char src[], void *dst, int maxlen) {
+ int i;
+ unsigned char offset;
+ for (i=0; i<maxlen*2; i++) {
+ //if ( src[i] == '\0') return i;
+ if ( src[i] >= '0' && src[i] <= '9' ) offset='0';
+ else if ( src[i] >= 'a' && src[i] <= 'f' ) offset='a' - 10;
+ else if ( src[i] >= 'A' && src[i] <= 'F' ) offset='A' - 10;
+ else break;
+
+ if ( i % 2 == 0 ) {
+ ((unsigned char *)dst)[i/2] = (src[i]-offset) << 4;
+ } else {
+ ((unsigned char *)dst)[i/2] += (src[i]-offset);
+ }
+ }
+ return i/2;
+}
+
+// Indicate the position of the bit that is on
+// If multiple bits activated, returns -2
+// If no bits activated, return -1
+int bit_position(uint16_t flags) {
+ int i, pos;
+ pos=-1; // Not found yet
+ for (i=0;i<16;i++) {
+ if ( (flags >> i) & 0x0001 ) {
+ if ( pos == -1 ) {
+ pos=i;
+ } else {
+ return -2;
+ }
+ }
+ }
+ return pos;
+}
diff --git a/reverse-engineering/dosbox_snif/utils.h b/reverse-engineering/dosbox_snif/utils.h
new file mode 100644
index 0000000..a7031a8
--- /dev/null
+++ b/reverse-engineering/dosbox_snif/utils.h
@@ -0,0 +1,11 @@
+#ifndef _UTILS_H
+#define _UTILS_H
+
+#include <stdint.h>
+
+int tcp_client_init(char host[], char port[], int *sockfd);
+void flatten(char *seg_off);
+int hexascii2bin(char src[], void *dst, int maxlen);
+int bit_position(uint16_t flags);
+
+#endif /*_UTIL_H*/
diff --git a/reverse-engineering/work/seg_code_0208.txt b/reverse-engineering/work/seg_code_0208.txt
index 0efbed8..21a4ca0 100644
--- a/reverse-engineering/work/seg_code_0208.txt
+++ b/reverse-engineering/work/seg_code_0208.txt
@@ -1736,7 +1736,7 @@ main_loop_ingame:
00000F49 3C30 cmp al,0x30 if ( al == 0x30 ) goto no_lemm_left;
00000F4B 7502 jnz 0xf4f //
00000F4D EB57 jmp short 0xfa6 //
-00000F4F 803E2800FF cmp byte [0x28],0xff if ( ! [0x28] ) {
+00000F4F 803E2800FF cmp byte [0x28],0xff if ( ! paused ) {
00000F54 7437 jz 0xf8d //
00000F56 FE0E8200 dec byte [0x82] [0x82]--;
00000F5A 7531 jnz 0xf8d if ( [0x82] == 0 ) {
@@ -2769,7 +2769,7 @@ no_lemm_left:
0000182E C3 ret
void move_lemmings() {
-0000182F 803E2800FF cmp byte [0x28],0xff if ([0x28] == 0xff) { #
+0000182F 803E2800FF cmp byte [0x28],0xff if ( paused ) {
00001834 7503 jnz 0x1839
00001836 E9DC00 jmp word 0x1915 [0x4d] = 0; #
return;
@@ -2800,7 +2800,7 @@ no_lemm_left:
0000186F 7403 jz 0x1874 //
00001871 E9350E jmp word 0x26a9 //
00001874 8B4408 mov ax,[si+0x8] //
-00001877 23C0 and ax,ax if ( lemm->state.word == 0x0 )
+00001877 23C0 and ax,ax if ( lemm->state.raw == 0x0 )
00001879 7503 jnz 0x187e goto lbl_walking;
0000187B E9DF00 jmp word 0x195d //
0000187E A90200 test ax,0x2 if ( lemm->state.bits.s_exploding )
@@ -2882,7 +2882,7 @@ label1:
0000193A 7506 jnz 0x1942 //
0000193C FE064900 inc byte [0x49] //
00001940 EBD9 jmp short 0x191b //
-00001942 F744080380 test word [si+0x8],0x8003 if ( lemm->state.word & (s_exploding2 | s_splatting | s_exploding) == 0 ) {
+00001942 F744080380 test word [si+0x8],0x8003 if ( lemm->state.raw & (s_exploding2 | s_splatting | s_exploding) == 0 ) {
00001947 7504 jnz 0x194d lemm.expl_countdown = 79;
00001949 C644204F mov byte [si+0x20],0x4f }
0000194D FE064900 inc byte [0x49] [0x49]++;
@@ -4087,7 +4087,7 @@ lbl_anim_but_no_move:
000026B3 7403 jz 0x26b8 if ( lemm->spr_frame != 7 ) {
000026B5 E949F2 jmp word 0x1901 goto next_lemming;
}
-000026B8 C744080000 mov word [si+0x8],0x0 lemm->state.word = s_walking;
+000026B8 C744080000 mov word [si+0x8],0x0 lemm->state.raw = s_walking;
000026BD C7440A0000 mov word [si+0xa],0x0 //???
000026C2 C7440C0000 mov word [si+0xc],0x0 lemm->spr_data_ptr = 0;
000026C7 C744105A00 mov word [si+0x10],0x5a //???
@@ -4108,7 +4108,7 @@ lbl_anim_but_no_move:
000026F8 B001 mov al,0x1
000026FA FE4C20 dec byte [si+0x20] lemm.expl_countdown--;
000026FD 7555 jnz 0x2754 if ( lemm.expl_countdown == 0 ) {
-000026FF F744080454 test word [si+0x8],0x5404 if ( lemm->state.word == 0x5404 ) { //WTF?? #
+000026FF F744080454 test word [si+0x8],0x5404 if ( lemm->state.raw == 0x5404 ) { //WTF?? #
00002704 7551 jnz 0x2757 //
00002706 814C080080 or word [si+0x8],0x8000 lemm->state.bits.s_exploding2 = 1;
0000270B C7440A0800 mov word [si+0xa],0x8 // ??? #
@@ -4333,7 +4333,7 @@ lbl_on_exit:
00002997 CD61 int 0x61
00002999 C3 ret
void spawn_lemming() {
-0000299A 803E2800FF cmp byte [0x28],0xff if ( ![0x28] || ![0x52] ) return; #
+0000299A 803E2800FF cmp byte [0x28],0xff if ( paused || ![0x52] ) return; #
0000299F 7503 jnz 0x29a4 //
000029A1 E99F00 jmp word 0x2a43 //
000029A4 803E5200FF cmp byte [0x52],0xff //
@@ -4390,7 +4390,7 @@ lbl_on_exit:
00002A43 C3 ret return;
}
void apply_skill() {
-00002A44 803E2800FF cmp byte [0x28],0xff if ( [0x28] || [0x4d] || ![0x60] ) return;
+00002A44 803E2800FF cmp byte [0x28],0xff if ( paused || [0x4d] || ![0x60] ) return;
00002A49 7463 jz 0x2aae //
00002A4B 803E4D00FF cmp byte [0x4d],0xff //
00002A50 7502 jnz 0x2a54 //
@@ -4441,7 +4441,7 @@ lbl_apply_exploder:
00002ABA 7441 jz 0x2afd //
00002ABC 807C2000 cmp byte [si+0x20],0x0 //
00002AC0 753B jnz 0x2afd //
-00002AC2 F7440803C0 test word [si+0x8],0xc003 if ( lemm->state.word & (s_exploding2 | s_dying | s_exploding | s_splatting) !=0 )
+00002AC2 F7440803C0 test word [si+0x8],0xc003 if ( lemm->state.raw & (s_exploding2 | s_dying | s_exploding | s_splatting) !=0 )
00002AC7 7534 jnz 0x2afd return;
00002AC9 FE0E6D00 dec byte [0x6d] sk_bomber--;
00002ACD C6066F0000 mov byte [0x6f],0x0 sk_bomber_tag=0;
@@ -5679,7 +5679,7 @@ try_other_candidate_for_mining:
000037EC 3C0C cmp al,0xc
000037EE 7503 jnz 0x37f3
000037F0 E99B00 jmp word 0x388e
-000037F3 803E2800FF cmp byte [0x28],0xff
+000037F3 803E2800FF cmp byte [0x28],0xff if ( ! paused )
000037F8 7503 jnz 0x37fd
000037FA E98C00 jmp word 0x3889
000037FD 803E810000 cmp byte [0x81],0x0
@@ -5734,7 +5734,7 @@ try_other_candidate_for_mining:
00003888 C3 ret
00003889 C6065F00FF mov byte [0x5f],0xff
0000388E C3 ret
-0000388F 803E2800FF cmp byte [0x28],0xff
+0000388F 803E2800FF cmp byte [0x28],0xff if ( paused )
00003894 74F8 jz 0x388e
00003896 C606CC1F00 mov byte [0x1fcc],0x0
0000389B A0CF1F mov al,[0x1fcf]
@@ -5753,10 +5753,10 @@ try_other_candidate_for_mining:
000038C1 80FB02 cmp bl,0x2
000038C4 7302 jnc 0x38c8
000038C6 EBC6 jmp short 0x388e
-000038C8 80362800FF xor byte [0x28],0xff
+000038C8 80362800FF xor byte [0x28],0xff paused = !paused;
000038CD A25000 mov [0x50],al
000038D0 EBBC jmp short 0x388e
-000038D2 803E2800FF cmp byte [0x28],0xff
+000038D2 803E2800FF cmp byte [0x28],0xff if ( paused )
000038D7 74B5 jz 0x388e
000038D9 22C0 and al,al
000038DB 742B jz 0x3908
@@ -12418,8 +12418,8 @@ try_other_candidate_for_mining:
000070B3 C3 ret
}
void unk_03() {
-000070B4 803E2800FF cmp byte [0x28],0xff
-000070B9 745A jz 0x7115
+000070B4 803E2800FF cmp byte [0x28],0xff if ( paused ) return;
+000070B9 745A jz 0x7115 //
000070BB BEC817 mov si,0x17c8
000070BE BFE80F mov di,0xfe8
000070C1 B92000 mov cx,0x20