int kdba_removebp(kdb_bp_t *bp) { /* * For hardware breakpoints, remove it from the active register, * for software breakpoints, restore the instruction stream. */ if (KDB_DEBUG(BP)) { kdb_printf("kdba_removebp bp_installed %d\n", bp->bp_installed); } if (bp->bp_installed) { if (bp->bp_hardtype) { if (KDB_DEBUG(BP)) { kdb_printf("kdb: removing hardware reg %ld at " kdb_bfd_vma_fmt "\n", bp->bp_hard->bph_reg, bp->bp_addr); } kdba_removedbreg(bp); } else { if (KDB_DEBUG(BP)) kdb_printf("kdb: restoring instruction 0x%x at " kdb_bfd_vma_fmt "\n", bp->bp_inst, bp->bp_addr); if (kdb_putword(bp->bp_addr, bp->bp_inst, 1)) return(1); } bp->bp_installed = 0; } return(0); }
int kdbgetsymval(const char *symname, kdb_symtab_t *symtab) { if (KDB_DEBUG(AR)) kdb_printf("kdbgetsymval: symname=%s, symtab=%p\n", symname, symtab); memset(symtab, 0, sizeof(*symtab)); if ((symtab->sym_start = kallsyms_lookup_name(symname))) { if (KDB_DEBUG(AR)) kdb_printf("kdbgetsymval: returns 1, symtab->sym_start=0x%lx\n", symtab->sym_start); return 1; } if (KDB_DEBUG(AR)) kdb_printf("kdbgetsymval: returns 0\n"); return 0; }
static int _kdb_bp_install(struct pt_regs *regs, kdb_bp_t *bp) { int ret; /* * Install the breakpoint, if it is not already installed. */ if (KDB_DEBUG(BP)) kdb_printf("%s: bp_installed %d\n", __func__, bp->bp_installed); if (!KDB_STATE(SSBPT)) bp->bp_delay = 0; if (bp->bp_installed) return 1; if (bp->bp_delay || (bp->bp_delayed && KDB_STATE(DOING_SS))) { if (KDB_DEBUG(BP)) kdb_printf("%s: delayed bp\n", __func__); kdb_handle_bp(regs, bp); return 0; } if (!bp->bp_type) ret = dbg_set_sw_break(bp->bp_addr); else ret = arch_kgdb_ops.set_hw_breakpoint(bp->bp_addr, bp->bph_length, bp->bp_type); if (ret == 0) { bp->bp_installed = 1; } else { kdb_printf("%s: failed to set breakpoint at 0x%lx\n", __func__, bp->bp_addr); #ifdef CONFIG_DEBUG_RODATA if (!bp->bp_type) { kdb_printf("Software breakpoints are unavailable.\n" " Change the kernel CONFIG_DEBUG_RODATA=n\n" " OR use hw breaks: help bph\n"); } #endif return 1; } return 0; }
// parses a RRGGBB string into array of bytes // that specify Konami color: r,0,g,0,b,0. void MakeKonamiColor(char* str, BYTE* buf) { ZeroMemory(buf, 6); if (lstrlen(str) != 6) return; int num = 0; if (sscanf(str,"%x",&num)!=1) return; buf[0] = (BYTE)((num >> 16) & 0xff); buf[2] = (BYTE)((num >> 8) & 0xff); buf[4] = (BYTE)(num & 0xff); KDB_DEBUG(klog, (klog, "Konami color: %x,%x,%x,%x,%x,%x\n", buf[0],buf[1],buf[2],buf[3],buf[4],buf[5])); }
int kdba_installbp(struct pt_regs *regs, kdb_bp_t *bp) { /* * Install the breakpoint, if it is not already installed. */ if (KDB_DEBUG(BP)) { kdb_printf("kdba_installbp bp_installed %d\n", bp->bp_installed); } if (!KDB_STATE(SSBPT)) bp->bp_delay = 0; if (!bp->bp_installed) { if (bp->bp_hardtype) { kdba_installdbreg(bp); bp->bp_installed = 1; if (KDB_DEBUG(BP)) { kdb_printf("kdba_installbp hardware reg %ld at " kdb_bfd_vma_fmt "\n", bp->bp_hard->bph_reg, bp->bp_addr); } } else if (bp->bp_delay) { if (KDB_DEBUG(BP)) kdb_printf("kdba_installbp delayed bp\n"); kdba_handle_bp(regs, bp); } else { if (kdb_getarea_size(&(bp->bp_inst), bp->bp_addr, 1) || kdb_putword(bp->bp_addr, IA32_BREAKPOINT_INSTRUCTION, 1)) { kdb_printf("kdba_installbp failed to set software breakpoint at " kdb_bfd_vma_fmt "\n", bp->bp_addr); return(1); } bp->bp_installed = 1; if (KDB_DEBUG(BP)) kdb_printf("kdba_installbp instruction 0x%x at " kdb_bfd_vma_fmt "\n", IA32_BREAKPOINT_INSTRUCTION, bp->bp_addr); } } return(0); }
/* * kdb_bp_remove * * Remove kdb_breakpoints upon entry to the kernel debugger. * * Parameters: * None. * Outputs: * None. * Returns: * None. * Locking: * None. * Remarks: */ void kdb_bp_remove(void) { int i; for (i = KDB_MAXBPT - 1; i >= 0; i--) { kdb_bp_t *bp = &kdb_breakpoints[i]; if (KDB_DEBUG(BP)) { kdb_printf("%s: bp %d bp_enabled %d\n", __func__, i, bp->bp_enabled); } if (bp->bp_enabled) _kdb_bp_remove(bp); } }
/* * kdb_bp_install * * Install kdb_breakpoints prior to returning from the * kernel debugger. This allows the kdb_breakpoints to be set * upon functions that are used internally by kdb, such as * printk(). This function is only called once per kdb session. */ void kdb_bp_install(struct pt_regs *regs) { int i; for (i = 0; i < KDB_MAXBPT; i++) { kdb_bp_t *bp = &kdb_breakpoints[i]; if (KDB_DEBUG(BP)) { kdb_printf("%s: bp %d bp_enabled %d\n", __func__, i, bp->bp_enabled); } if (bp->bp_enabled) _kdb_bp_install(regs, bp); } }
static void kdb_handle_bp(struct pt_regs *regs, kdb_bp_t *bp) { if (KDB_DEBUG(BP)) kdb_printf("regs->ip = 0x%lx\n", instruction_pointer(regs)); /* * Setup single step */ kdb_setsinglestep(regs); /* * Reset delay attribute */ bp->bp_delay = 0; bp->bp_delayed = 1; }
void kdb_bp_remove_global(void) { int i; for(i=KDB_MAXBPT-1; i>=0; i--) { kdb_bp_t *bp = &kdb_breakpoints[i]; if (KDB_DEBUG(BP)) { kdb_printf("kdb_bp_remove_global bp %d bp_enabled %d bp_global %d\n", i, bp->bp_enabled, bp->bp_global); } if (kdb_is_installable_global_bp(bp)) kdba_removebp(bp); } }
void kdb_bp_install_global(struct pt_regs *regs) { int i; for(i=0; i<KDB_MAXBPT; i++) { kdb_bp_t *bp = &kdb_breakpoints[i]; if (KDB_DEBUG(BP)) { kdb_printf("kdb_bp_install_global bp %d bp_enabled %d bp_global %d\n", i, bp->bp_enabled, bp->bp_global); } /* HW BP local or global are installed in kdb_bp_install_local*/ if (kdb_is_installable_global_bp(bp)) kdba_installbp(regs, bp); } }
void kdb_bp_install_local(struct pt_regs *regs) { int i; for(i=0; i<KDB_MAXBPT; i++) { kdb_bp_t *bp = &kdb_breakpoints[i]; if (KDB_DEBUG(BP)) { kdb_printf("kdb_bp_install_local bp %d bp_enabled %d bp_global %d cpu %d bp_cpu %d\n", i, bp->bp_enabled, bp->bp_global, smp_processor_id(), bp->bp_cpu); } if (kdb_is_installable_local_bp(bp)) kdba_installbp(regs, bp); } }
kdb_dbtrap_t kdba_bp_trap(struct pt_regs *regs, int error_unused) { int i; kdb_dbtrap_t rv; kdb_bp_t *bp; if (KDB_NULL_REGS(regs)) return KDB_DB_NOBPT; /* * Determine which breakpoint was encountered. */ if (KDB_DEBUG(BP)) kdb_printf("kdba_bp_trap: rip=0x%lx (not adjusted) " "eflags=0x%lx ef=0x%p rsp=0x%lx\n", regs->rip, regs->eflags, regs, regs->rsp); rv = KDB_DB_NOBPT; /* Cause kdb() to return */ for(i=0, bp=kdb_breakpoints; i<KDB_MAXBPT; i++, bp++) { if (bp->bp_free) continue; if (!bp->bp_global && bp->bp_cpu != smp_processor_id()) continue; if ((void *)bp->bp_addr == (void *)(regs->rip - bp->bp_adjust)) { /* Hit this breakpoint. */ regs->rip -= bp->bp_adjust; kdb_printf("Instruction(i) breakpoint #%d at 0x%lx (adjusted)\n", i, regs->rip); kdb_id1(regs->rip); rv = KDB_DB_BPT; bp->bp_delay = 1; /* SSBPT is set when the kernel debugger must single * step a task in order to re-establish an instruction * breakpoint which uses the instruction replacement * mechanism. It is cleared by any action that removes * the need to single-step the breakpoint. */ KDB_STATE_SET(SSBPT); break; } } return rv; }
static void kdba_handle_bp(struct pt_regs *regs, kdb_bp_t *bp) { if (KDB_NULL_REGS(regs)) return; if (KDB_DEBUG(BP)) kdb_printf("regs->rip = 0x%lx\n", regs->rip); /* * Setup single step */ kdba_setsinglestep(regs); /* * Reset delay attribute */ bp->bp_delay = 0; bp->bp_delayed = 1; }
/* * kdbnearsym - Return the name of the symbol with the nearest address * less than 'addr'. * * Parameters: * addr Address to check for symbol near * symtab Structure to receive results * Returns: * 0 No sections contain this address, symtab zero filled * 1 Address mapped to module/symbol/section, data in symtab * Remarks: * 2.6 kallsyms has a "feature" where it unpacks the name into a * string. If that string is reused before the caller expects it * then the caller sees its string change without warning. To * avoid cluttering up the main kdb code with lots of kdb_strdup, * tests and kfree calls, kdbnearsym maintains an LRU list of the * last few unique strings. The list is sized large enough to * hold active strings, no kdb caller of kdbnearsym makes more * than ~20 later calls before using a saved value. */ int kdbnearsym(unsigned long addr, kdb_symtab_t *symtab) { int ret = 0; unsigned long symbolsize = 0; unsigned long offset = 0; #define knt1_size 128 /* must be >= kallsyms table size */ char *knt1 = NULL; if (KDB_DEBUG(AR)) kdb_printf("kdbnearsym: addr=0x%lx, symtab=%p\n", addr, symtab); memset(symtab, 0, sizeof(*symtab)); if (addr < 4096) goto out; knt1 = debug_kmalloc(knt1_size, GFP_ATOMIC); if (!knt1) { kdb_printf("kdbnearsym: addr=0x%lx cannot kmalloc knt1\n", addr); goto out; } symtab->sym_name = kallsyms_lookup(addr, &symbolsize , &offset, (char **)(&symtab->mod_name), knt1); if (offset > 8*1024*1024) { symtab->sym_name = NULL; addr = offset = symbolsize = 0; } symtab->sym_start = addr - offset; symtab->sym_end = symtab->sym_start + symbolsize; ret = symtab->sym_name != NULL && *(symtab->sym_name) != '\0'; if (ret) { int i; /* Another 2.6 kallsyms "feature". Sometimes the sym_name is * set but the buffer passed into kallsyms_lookup is not used, * so it contains garbage. The caller has to work out which * buffer needs to be saved. * * What was Rusty smoking when he wrote that code? */ if (symtab->sym_name != knt1) { strncpy(knt1, symtab->sym_name, knt1_size); knt1[knt1_size-1] = '\0'; } for (i = 0; i < ARRAY_SIZE(kdb_name_table); ++i) { if (kdb_name_table[i] && strcmp(kdb_name_table[i], knt1) == 0) break; } if (i >= ARRAY_SIZE(kdb_name_table)) { debug_kfree(kdb_name_table[0]); memcpy(kdb_name_table, kdb_name_table+1, sizeof(kdb_name_table[0]) * (ARRAY_SIZE(kdb_name_table)-1)); } else { debug_kfree(knt1); knt1 = kdb_name_table[i]; memcpy(kdb_name_table+i, kdb_name_table+i+1, sizeof(kdb_name_table[0]) * (ARRAY_SIZE(kdb_name_table)-i-1)); } i = ARRAY_SIZE(kdb_name_table) - 1; kdb_name_table[i] = knt1; symtab->sym_name = kdb_name_table[i]; knt1 = NULL; } if (symtab->mod_name == NULL) symtab->mod_name = "kernel"; if (KDB_DEBUG(AR)) kdb_printf("kdbnearsym: returns %d symtab->sym_start=0x%lx, " "symtab->mod_name=%p, symtab->sym_name=%p (%s)\n", ret, symtab->sym_start, symtab->mod_name, symtab->sym_name, symtab->sym_name); out: debug_kfree(knt1); return ret; }
kdb_dbtrap_t kdba_db_trap(struct pt_regs *regs, int error_unused) { kdb_machreg_t dr6; kdb_machreg_t dr7; int rw, reg; int i; kdb_dbtrap_t rv = KDB_DB_BPT; kdb_bp_t *bp; if (KDB_NULL_REGS(regs)) return KDB_DB_NOBPT; dr6 = kdba_getdr6(); dr7 = kdba_getdr7(); if (KDB_DEBUG(BP)) kdb_printf("kdb: dr6 0x%lx dr7 0x%lx\n", dr6, dr7); if (dr6 & DR6_BS) { if (KDB_STATE(SSBPT)) { if (KDB_DEBUG(BP)) kdb_printf("ssbpt\n"); KDB_STATE_CLEAR(SSBPT); for(i=0,bp=kdb_breakpoints; i < KDB_MAXBPT; i++, bp++) { if (KDB_DEBUG(BP)) kdb_printf("bp 0x%p enabled %d delayed %d global %d cpu %d\n", bp, bp->bp_enabled, bp->bp_delayed, bp->bp_global, bp->bp_cpu); if (!bp->bp_enabled) continue; if (!bp->bp_global && bp->bp_cpu != smp_processor_id()) continue; if (KDB_DEBUG(BP)) kdb_printf("bp for this cpu\n"); if (bp->bp_delayed) { bp->bp_delayed = 0; if (KDB_DEBUG(BP)) kdb_printf("kdba_installbp\n"); kdba_installbp(regs, bp); if (!KDB_STATE(DOING_SS)) { regs->eflags &= ~EF_TF; return(KDB_DB_SSBPT); } break; } } if (i == KDB_MAXBPT) { kdb_printf("kdb: Unable to find delayed breakpoint\n"); } if (!KDB_STATE(DOING_SS)) { regs->eflags &= ~EF_TF; return(KDB_DB_NOBPT); } /* FALLTHROUGH */ } /* * KDB_STATE_DOING_SS is set when the kernel debugger is using * the processor trap flag to single-step a processor. If a * single step trap occurs and this flag is clear, the SS trap * will be ignored by KDB and the kernel will be allowed to deal * with it as necessary (e.g. for ptrace). */ if (!KDB_STATE(DOING_SS)) goto unknown; /* single step */ rv = KDB_DB_SS; /* Indicate single step */ if (KDB_STATE(DOING_SSB)) { unsigned char instruction[2]; kdb_id1(regs->rip); if (kdb_getarea(instruction, regs->rip) || (instruction[0]&0xf0) == 0xe0 || /* short disp jumps */ (instruction[0]&0xf0) == 0x70 || /* Misc. jumps */ instruction[0] == 0xc2 || /* ret */ instruction[0] == 0x9a || /* call */ (instruction[0]&0xf8) == 0xc8 || /* enter, leave, iret, int, */ ((instruction[0] == 0x0f) && ((instruction[1]&0xf0)== 0x80)) ) { /* * End the ssb command here. */ KDB_STATE_CLEAR(DOING_SSB); KDB_STATE_CLEAR(DOING_SS); } else { rv = KDB_DB_SSB; /* Indicate ssb - dismiss immediately */ } } else { /* * Print current insn */ kdb_printf("SS trap at "); kdb_symbol_print(regs->rip, NULL, KDB_SP_DEFAULT|KDB_SP_NEWLINE); kdb_id1(regs->rip); KDB_STATE_CLEAR(DOING_SS); } if (rv != KDB_DB_SSB) regs->eflags &= ~EF_TF; } if (dr6 & DR6_B0) { rw = DR7_RW0(dr7); reg = 0; goto handle; } if (dr6 & DR6_B1) { rw = DR7_RW1(dr7); reg = 1; goto handle; } if (dr6 & DR6_B2) { rw = DR7_RW2(dr7); reg = 2; goto handle; } if (dr6 & DR6_B3) { rw = DR7_RW3(dr7); reg = 3; goto handle; } if (rv > 0) goto handled; goto unknown; /* dismiss */ handle: /* * Set Resume Flag */ regs->eflags |= EF_RF; /* * Determine which breakpoint was encountered. */ for(i=0, bp=kdb_breakpoints; i<KDB_MAXBPT; i++, bp++) { if (!(bp->bp_free) && (bp->bp_global || bp->bp_cpu == smp_processor_id()) && (bp->bp_hard) && (bp->bp_hard->bph_reg == reg)) { /* * Hit this breakpoint. */ kdb_printf("%s breakpoint #%d at " kdb_bfd_vma_fmt "\n", kdba_rwtypes[rw], i, bp->bp_addr); /* * For an instruction breakpoint, disassemble * the current instruction. */ if (rw == 0) { kdb_id1(regs->rip); } goto handled; } } unknown: regs->eflags |= EF_RF; /* Supress further faults */ rv = KDB_DB_NOBPT; /* Cause kdb() to return */ handled: /* * Clear the pending exceptions. */ kdba_putdr6(0); return rv; }
int kdba_parsebp(int argc, const char **argv, int *nextargp, kdb_bp_t *bp) { int nextarg = *nextargp; int diag; kdbhard_bp_t *bph = &bp->bp_template; bph->bph_mode = 0; /* Default to instruction breakpoint */ bph->bph_length = 0; /* Length must be zero for insn bp */ if ((argc + 1) != nextarg) { if (strnicmp(argv[nextarg], "datar", sizeof("datar")) == 0) { bph->bph_mode = 3; } else if (strnicmp(argv[nextarg], "dataw", sizeof("dataw")) == 0) { bph->bph_mode = 1; } else if (strnicmp(argv[nextarg], "io", sizeof("io")) == 0) { bph->bph_mode = 2; } else if (strnicmp(argv[nextarg], "inst", sizeof("inst")) == 0) { bph->bph_mode = 0; } else { return KDB_ARGCOUNT; } bph->bph_length = 3; /* Default to 4 byte */ nextarg++; if ((argc + 1) != nextarg) { unsigned long len; diag = kdbgetularg((char *)argv[nextarg], &len); if (diag) return diag; if ((len > 4) || (len == 3)) return KDB_BADLENGTH; bph->bph_length = len; bph->bph_length--; /* Normalize for debug register */ nextarg++; } if ((argc + 1) != nextarg) return KDB_ARGCOUNT; /* * Indicate to architecture independent level that * a hardware register assignment is required to enable * this breakpoint. */ bph->bph_free = 0; } else { if (KDB_DEBUG(BP)) kdb_printf("kdba_bp: no args, forcehw is %d\n", bp->bp_forcehw); if (bp->bp_forcehw) { /* * We are forced to use a hardware register for this * breakpoint because either the bph or bpha * commands were used to establish this breakpoint. */ bph->bph_free = 0; } else { /* * Indicate to architecture dependent level that * the instruction replacement breakpoint technique * should be used for this breakpoint. */ bph->bph_free = 1; bp->bp_adjust = 1; /* software, int 3 is one byte */ } } if (bph->bph_mode != 2 && kdba_verify_rw(bp->bp_addr, bph->bph_length+1)) { kdb_printf("Invalid address for breakpoint, ignoring bp command\n"); return KDB_BADADDR; } *nextargp = nextarg; return 0; }
KitEntry* buildKitList(char* dir, int kitType) { WIN32_FIND_DATA fData; char pattern[4096]; ZeroMemory(pattern, 4096); KitEntry* list = NULL; KitEntry* p = NULL; HANDLE heap = GetProcessHeap(); lstrcpy(pattern, dir); if (kitType == PLAYERS) lstrcat(pattern, "KDB\\players\\uni???*.bin"); else if (kitType == GOALKEEPERS) lstrcat(pattern, "KDB\\goalkeepers\\uni???*.bin"); KDB_DEBUG(klog, (klog, "pattern = {%s}\n", pattern)); HANDLE hff = FindFirstFile(pattern, &fData); if (hff == INVALID_HANDLE_VALUE) { // none found. return NULL; } while(true) { // build new list element Kit* kit = (Kit*)HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(Kit)); if (kit != NULL) { ZeroMemory(kit->fileName, 255); lstrcpy(kit->fileName, fData.cFileName); ZeroMemory(kit->shirtBackNumber, 6); ZeroMemory(kit->shirtBackName, 6); ZeroMemory(kit->shirtFrontNumber, 6); ZeroMemory(kit->shortsNumber, 6); kit->collar = 2; kit->attDefined = 0; p = (KitEntry*)HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(KitEntry)); if (p != NULL) { // insert new element p->kit = kit; p->next = list; list = p; KDB_DEBUG(klog, (klog, "list->kit->fileName = {%s}\n", list->kit->fileName)); } else { HeapFree(heap, 0, kit); } } // proceed to next file if (!FindNextFile(hff, &fData)) break; } FindClose(hff); return list; }
KDB* kdbLoad(char* dir) { KDB_DEBUG_OPEN(klog, dir); KDB_DEBUG(klog, (klog, "Loading KDB...\n")); // initialize an empty database KDB* kdb = (KDB*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(KDB)); if (kdb == NULL) { fclose(klog); return NULL; } kdb->playerCount = kdb->goalkeeperCount = 0; ZeroMemory(kdb->players, sizeof(KitEntry*) * 256); ZeroMemory(kdb->goalkeepers, sizeof(KitEntry*) * 256); // get list of player kits KitEntry* kits = buildKitList(dir, PLAYERS); // traverse the list and place the kits into the database KitEntry* p = kits; KitEntry* q = NULL; while (p != NULL) { q = p->next; KDB_DEBUG(klog, (klog, "p->kit->filename = %s\n", p->kit->fileName)); int n = getTeamNumber(p->kit->fileName); if (n >= 0 && n <= 255) { p->next = kdb->players[n]; kdb->players[n] = p; kdb->playerCount += 1; KDB_DEBUG(klog, (klog, "[%03d] : %s\n", n, p->kit->fileName)); } p = q; } // get list of goalkeeper kits kits = buildKitList(dir, GOALKEEPERS); // traverse the list and place the kits into the database p = kits; q = NULL; while (p != NULL) { q = p->next; KDB_DEBUG(klog, (klog, "p->kit->filename = %s\n", p->kit->fileName)); int n = getTeamNumber(p->kit->fileName); if (n >= 0 && n <= 255) { p->next = kdb->goalkeepers[n]; kdb->goalkeepers[n] = p; kdb->goalkeeperCount += 1; KDB_DEBUG(klog, (klog, "[%03d] : %s\n", n, p->kit->fileName)); } p = q; } // read the attributes from attrib.cfg file int currTeam = -1; Kit* currUni = NULL; Ball* currBall = NULL; // default is players // (for compatibility with attrib.cfg files from older kitservers int group = GROUP_PLAYERS; char buf[4096]; ZeroMemory(buf, 4096); lstrcpy(buf, dir); lstrcat(buf, "KDB\\attrib.cfg"); FILE* att = fopen(buf, "rt"); if (att != NULL) { // go line by line while (!feof(att)) { ZeroMemory(buf, 4096); fgets(buf, 4096, att); if (lstrlen(buf) == 0) break; // strip off comments char* comm = strstr(buf, "#"); if (comm != NULL) comm[0] = '\0'; // look for start of the section char* start = strstr(buf, "["); if (start != NULL) { char* end = strstr(start+1,"]"); if (end != NULL) { // new section char name[255]; ZeroMemory(name, 255); lstrcpy(name, start+1); name[end-start-1] = '\0'; KDB_DEBUG(klog, (klog, "section: {%s}\n", name)); // check if we changed groups if (lstrcmpi(name, "Players")==0) { group = GROUP_PLAYERS; currTeam = -1; currUni = NULL; continue; } else if (lstrcmpi(name, "Goalkeepers")==0) { group = GROUP_GOALKEEPERS; currTeam = -1; currUni = NULL; continue; } else if (lstrcmpi(name, "Balls")==0) { group = GROUP_BALLS; currTeam = -1; currUni = NULL; continue; } if (group == GROUP_PLAYERS) { // this has to be a kit file start[7] = '\0'; if (sscanf(start+4,"%d",&currTeam)==1) { KDB_DEBUG(klog, (klog, "looking up uniform for team: {%d}\n", currTeam)); // lookup name in KDB KitEntry* p = kdb->players[currTeam]; while (p != NULL) { if (lstrcmp(p->kit->fileName, name)==0) { currUni = p->kit; break; } p = p->next; } if (p == NULL) { currTeam = -1; // didn't find such uniform in KDB currUni = NULL; } } } else if (group == GROUP_GOALKEEPERS) { // this has to be a kit file start[7] = '\0'; if (sscanf(start+4,"%d",&currTeam)==1) { KDB_DEBUG(klog, (klog, "looking up uniform for team: {%d}\n", currTeam)); // lookup name in KDB KitEntry* p = kdb->goalkeepers[currTeam]; while (p != NULL) { if (lstrcmp(p->kit->fileName, name)==0) { currUni = p->kit; break; } p = p->next; } if (p == NULL) { currTeam = -1; // didn't find such uniform in KDB currUni = NULL; } } } else if (group == GROUP_BALLS) { // this has to be a ball file KDB_DEBUG(klog, (klog, "New ball key: {%s}\n", name)); currBall = (Ball*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Ball)); if (currBall != NULL) { lstrcpy(currBall->texFileName, name); // insert into list of balls BallEntry* be = (BallEntry*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BallEntry)); if (be != NULL) { be->ball = currBall; be->next = kdb->balls; kdb->balls = be; } } } } // end if (end ... } // otherwise try to read attributes else { if (currTeam != -1 && (group == GROUP_PLAYERS || group == GROUP_GOALKEEPERS)) { char key[80]; ZeroMemory(key, 80); char value[80]; ZeroMemory(value, 80); if (sscanf(buf,"%s = %s",key,value)==2) { KDB_DEBUG(klog, (klog, "key: {%s} has value: {%s}\n", key, value)); BYTE color[6]; if (lstrcmp(key, "shirt.backNumber")==0) { MakeKonamiColor(value, color); memcpy(currUni->shirtBackNumber, color, 6); currUni->attDefined |= SHIRT_BACK_NUMBER; } else if (lstrcmp(key, "shirt.backName")==0) { MakeKonamiColor(value, color); memcpy(currUni->shirtBackName, color, 6); currUni->attDefined |= SHIRT_BACK_NAME; } else if (lstrcmp(key, "shirt.frontNumber")==0) { MakeKonamiColor(value, color); memcpy(currUni->shirtFrontNumber, color, 6); currUni->attDefined |= SHIRT_FRONT_NUMBER; } else if (lstrcmp(key, "shorts.number")==0) { MakeKonamiColor(value, color); memcpy(currUni->shortsNumber, color, 6); currUni->attDefined |= SHORTS_NUMBER; } else if (lstrcmp(key, "collar")==0) { currUni->collar = (lstrcmp(value,"yes")==0) ? 0 : 2; currUni->attDefined |= COLLAR; } } } else { if (group == GROUP_BALLS && currBall != NULL) { char key[255]; ZeroMemory(key, 255); sscanf(buf, "%s", key); if (lstrcmp(key, "ball.name")==0) { char* startQuote = strstr(buf, "\""); if (startQuote == NULL) continue; char* endQuote = strstr(startQuote + 1, "\""); if (endQuote == NULL) continue; memcpy(currBall->name, startQuote + 1, endQuote - startQuote - 1); KDB_DEBUG(klog, (klog, "key: {%s} has value: {%s}\n", key, currBall->name)); } else if (lstrcmp(key, "ball.model")==0) { char* startQuote = strstr(buf, "\""); if (startQuote == NULL) continue; char* endQuote = strstr(startQuote + 1, "\""); if (endQuote == NULL) continue; memcpy(currBall->mdlFileName, startQuote + 1, endQuote - startQuote - 1); KDB_DEBUG(klog, (klog, "key: {%s} has value: {%s}\n", key, currBall->mdlFileName)); } } } } // end else } fclose(att); } KDB_DEBUG(klog, (klog, "attributes read.\n")); // cycle the uniform lists, adding a "dummy" kits // and a "dummy" ball as well HANDLE heap = GetProcessHeap(); for (int i=0; i<256; i++) { // PLAYERS KitEntry* p = kdb->players[i]; if (p != NULL) { KitEntry* dummy = (KitEntry*)HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(KitEntry)); dummy->kit = (Kit*)HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(Kit)); dummy->kit->fileName[0] = 'x'; dummy->kit->attDefined = 0; dummy->next = NULL; // append dummy kit at the end while (p->next != NULL) p = p->next; p->next = dummy; dummy->next = kdb->players[i]; } // GOALKEEPERS p = kdb->goalkeepers[i]; if (p != NULL) { KitEntry* dummy = (KitEntry*)HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(KitEntry)); dummy->kit = (Kit*)HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(Kit)); dummy->kit->fileName[0] = 'x'; dummy->kit->attDefined = 0; dummy->next = NULL; // append dummy kit at the end while (p->next != NULL) p = p->next; p->next = dummy; dummy->next = kdb->goalkeepers[i]; } } KDB_DEBUG(klog, (klog, "PL and GK cycled.\n")); // insert the dummy ball at the front if (kdb->balls != NULL) { BallEntry* dummy = (BallEntry*)HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(BallEntry)); dummy->ball = (Ball*)HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(Ball)); dummy->ball->texFileName[0] = 'x'; dummy->next = kdb->balls; kdb->balls = dummy; } // now reverse the list BallEntry* reversed = NULL; BallEntry* bp = kdb->balls; while (bp != NULL) { BallEntry* bq = bp->next; bp->next = reversed; reversed = bp; bp = bq; } kdb->balls = reversed; KDB_DEBUG(klog, (klog, "balls reversed.\n")); // now cycle it bp = kdb->balls; if (bp != NULL) { while (bp->next != NULL) bp = bp->next; bp->next = kdb->balls; } KDB_DEBUG(klog, (klog, "balls cycled.\n")); KDB_DEBUG(klog, (klog, "KDB loaded.\n")); KDB_DEBUG_CLOSE(klog); return kdb; }