# HG changeset patch # User Michael Pavone # Date 1632291454 25200 # Node ID b119e0de9a708b6ce733f55758f13b96bf1ec660 # Parent 804954731e3f92fe36a71d9d741ac787a1f730f6 Strip out mega wifi support and debugger diff -r 804954731e3f -r b119e0de9a70 Makefile --- a/Makefile Thu Aug 05 23:48:41 2021 -0700 +++ b/Makefile Tue Sep 21 23:17:34 2021 -0700 @@ -218,11 +218,11 @@ #MAINOBJS=blastem.o system.o genesis.o debug.o gdb_remote.o vdp.o $(RENDEROBJS) io.o romdb.o hash.o menu.o xband.o MAINOBJS=blastem.o system.o genesis.o vdp.o $(RENDEROBJS) io.o romdb.o hash.o menu.o xband.o \ - realtec.o i2c.o nor.o sega_mapper.o multi_game.o megawifi.o $(NET) serialize.o $(TERMINAL) $(CONFIGOBJS) gst.o \ + realtec.o i2c.o nor.o sega_mapper.o multi_game.o $(NET) serialize.o $(TERMINAL) $(CONFIGOBJS) gst.o \ $(M68KOBJS) $(TRANSOBJS) $(AUDIOOBJS) saves.o zip.o bindings.o jcart.o gen_player.o LIBOBJS=libblastem.o system.o genesis.o debug.o gdb_remote.o vdp.o io.o romdb.o hash.o xband.o realtec.o \ - i2c.o nor.o sega_mapper.o multi_game.o megawifi.o $(NET) serialize.o $(TERMINAL) $(CONFIGOBJS) gst.o \ + i2c.o nor.o sega_mapper.o multi_game.o $(NET) serialize.o $(TERMINAL) $(CONFIGOBJS) gst.o \ $(M68KOBJS) $(TRANSOBJS) $(AUDIOOBJS) saves.o jcart.o rom.db.o gen_player.o $(LIBZOBJS) ifdef NONUKLEAR diff -r 804954731e3f -r b119e0de9a70 debug.c --- a/debug.c Thu Aug 05 23:48:41 2021 -0700 +++ b/debug.c Tue Sep 21 23:17:34 2021 -0700 @@ -113,999 +113,22 @@ void debugger_print(m68k_context *context, char format_char, char *param, uint32_t address) { - uint32_t value; - char format[8]; - strcpy(format, "%s: %d\n"); - switch (format_char) - { - case 'x': - case 'X': - case 'd': - case 'c': - format[5] = format_char; - break; - case '\0': - break; - default: - fprintf(stderr, "Unrecognized format character: %c\n", format_char); - } - if (param[0] == 'd' && param[1] >= '0' && param[1] <= '7') { - value = context->dregs[param[1]-'0']; - if (param[2] == '.') { - if (param[3] == 'w') { - value &= 0xFFFF; - } else if (param[3] == 'b') { - value &= 0xFF; - } - } - } else if (param[0] == 'a' && param[1] >= '0' && param[1] <= '7') { - value = context->aregs[param[1]-'0']; - if (param[2] == '.') { - if (param[3] == 'w') { - value &= 0xFFFF; - } else if (param[3] == 'b') { - value &= 0xFF; - } - } - } else if (param[0] == 's' && param[1] == 'r') { - value = (context->status << 8); - for (int flag = 0; flag < 5; flag++) { - value |= context->flags[flag] << (4-flag); - } - } else if(param[0] == 'c') { - value = context->current_cycle; - } else if(param[0] == 'f') { - genesis_context *gen = context->system; - value = gen->vdp->frame; - } else if (param[0] == 'p' && param[1] == 'c') { - value = address; - } else if ((param[0] == '0' && param[1] == 'x') || param[0] == '$') { - char *after; - uint32_t p_addr = strtol(param+(param[0] == '0' ? 2 : 1), &after, 16); - if (after[0] == '.' && after[1] == 'l') { - value = m68k_read_long(p_addr, context); - } else if (after[0] == '.' && after[1] == 'b') { - value = m68k_read_byte(p_addr, context); - } else { - value = m68k_read_word(p_addr, context); - } - } else if(param[0] == '(' && (param[1] == 'a' || param[1] == 'd') && param[2] >= '0' && param[2] <= '7' && param[3] == ')') { - uint8_t reg = param[2] - '0'; - uint32_t p_addr = param[1] == 'a' ? context->aregs[reg] : context->dregs[reg]; - if (param[4] == '.' && param[5] == 'l') { - value = m68k_read_long(p_addr, context); - } else if (param[4] == '.' && param[5] == 'b') { - value = m68k_read_byte(p_addr, context); - } else { - value = m68k_read_word(p_addr, context); - } - } else { - fprintf(stderr, "Unrecognized parameter to p: %s\n", param); - return; - } - printf(format, param, value); } #ifndef NO_Z80 void zdebugger_print(z80_context * context, char format_char, char * param) { - uint32_t value; - char format[8]; - strcpy(format, "%s: %d\n"); - genesis_context *system = context->system; - switch (format_char) - { - case 'x': - case 'X': - case 'd': - case 'c': - format[5] = format_char; - break; - case '\0': - break; - default: - fprintf(stderr, "Unrecognized format character: %c\n", format_char); - } - switch (param[0]) - { -#ifndef NEW_CORE - case 'a': - if (param[1] == 'f') { - if(param[2] == '\'') { - value = context->alt_regs[Z80_A] << 8; - value |= context->alt_flags[ZF_S] << 7; - value |= context->alt_flags[ZF_Z] << 6; - value |= context->alt_flags[ZF_H] << 4; - value |= context->alt_flags[ZF_PV] << 2; - value |= context->alt_flags[ZF_N] << 1; - value |= context->alt_flags[ZF_C]; - } else { - value = context->regs[Z80_A] << 8; - value |= context->flags[ZF_S] << 7; - value |= context->flags[ZF_Z] << 6; - value |= context->flags[ZF_H] << 4; - value |= context->flags[ZF_PV] << 2; - value |= context->flags[ZF_N] << 1; - value |= context->flags[ZF_C]; - } - } else if(param[1] == '\'') { - value = context->alt_regs[Z80_A]; - } else { - value = context->regs[Z80_A]; - } - break; - case 'b': - if (param[1] == 'c') { - if(param[2] == '\'') { - value = context->alt_regs[Z80_B] << 8; - value |= context->alt_regs[Z80_C]; - } else { - value = context->regs[Z80_B] << 8; - value |= context->regs[Z80_C]; - } - } else if(param[1] == '\'') { - value = context->alt_regs[Z80_B]; - } else if(param[1] == 'a') { - value = context->bank_reg << 15; - } else { - value = context->regs[Z80_B]; - } - break; - case 'c': - if(param[1] == '\'') { - value = context->alt_regs[Z80_C]; - } else if(param[1] == 'y') { - value = context->current_cycle; - } else { - value = context->regs[Z80_C]; - } - break; - case 'd': - if (param[1] == 'e') { - if(param[2] == '\'') { - value = context->alt_regs[Z80_D] << 8; - value |= context->alt_regs[Z80_E]; - } else { - value = context->regs[Z80_D] << 8; - value |= context->regs[Z80_E]; - } - } else if(param[1] == '\'') { - value = context->alt_regs[Z80_D]; - } else { - value = context->regs[Z80_D]; - } - break; - case 'e': - if(param[1] == '\'') { - value = context->alt_regs[Z80_E]; - } else { - value = context->regs[Z80_E]; - } - break; - case 'f': - if(param[2] == '\'') { - value = context->alt_flags[ZF_S] << 7; - value |= context->alt_flags[ZF_Z] << 6; - value |= context->alt_flags[ZF_H] << 4; - value |= context->alt_flags[ZF_PV] << 2; - value |= context->alt_flags[ZF_N] << 1; - value |= context->alt_flags[ZF_C]; - } else { - value = context->flags[ZF_S] << 7; - value |= context->flags[ZF_Z] << 6; - value |= context->flags[ZF_H] << 4; - value |= context->flags[ZF_PV] << 2; - value |= context->flags[ZF_N] << 1; - value |= context->flags[ZF_C]; - } - break; - case 'h': - if (param[1] == 'l') { - if(param[2] == '\'') { - value = context->alt_regs[Z80_H] << 8; - value |= context->alt_regs[Z80_L]; - } else { - value = context->regs[Z80_H] << 8; - value |= context->regs[Z80_L]; - } - } else if(param[1] == '\'') { - value = context->alt_regs[Z80_H]; - } else { - value = context->regs[Z80_H]; - } - break; - case 'l': - if(param[1] == '\'') { - value = context->alt_regs[Z80_L]; - } else { - value = context->regs[Z80_L]; - } - break; - case 'i': - if(param[1] == 'x') { - if (param[2] == 'h') { - value = context->regs[Z80_IXH]; - } else if(param[2] == 'l') { - value = context->regs[Z80_IXL]; - } else { - value = context->regs[Z80_IXH] << 8; - value |= context->regs[Z80_IXL]; - } - } else if(param[1] == 'y') { - if (param[2] == 'h') { - value = context->regs[Z80_IYH]; - } else if(param[2] == 'l') { - value = context->regs[Z80_IYL]; - } else { - value = context->regs[Z80_IYH] << 8; - value |= context->regs[Z80_IYL]; - } - } else if(param[1] == 'n') { - value = context->int_cycle; - } else if(param[1] == 'f' && param[2] == 'f' && param[3] == '1') { - value = context->iff1; - } else if(param[1] == 'f' && param[2] == 'f' && param[3] == '2') { - value = context->iff2; - } else { - value = context->im; - } - break; -#endif - case 's': - if (param[1] == 'p') { - value = context->sp; - } - break; - case '0': - if (param[1] == 'x') { - uint16_t p_addr = strtol(param+2, NULL, 16); - value = read_byte(p_addr, (void **)context->mem_pointers, &context->options->gen, context); - } - break; - } - printf(format, param, value); } z80_context * zdebugger(z80_context * context, uint16_t address) { - static char last_cmd[1024]; - char input_buf[1024]; - static uint16_t branch_t; - static uint16_t branch_f; - z80inst inst; - genesis_context *system = context->system; - init_terminal(); - //Check if this is a user set breakpoint, or just a temporary one - bp_def ** this_bp = find_breakpoint(&zbreakpoints, address); - if (*this_bp) { - printf("Z80 Breakpoint %d hit\n", (*this_bp)->index); - } else { - zremove_breakpoint(context, address); - } - uint8_t * pc = get_native_pointer(address, (void **)context->mem_pointers, &context->Z80_OPTS->gen); - if (!pc) { - fatal_error("Failed to get native pointer on entering Z80 debugger at address %X\n", address); - } - for (disp_def * cur = zdisplays; cur; cur = cur->next) { - zdebugger_print(context, cur->format_char, cur->param); - } - uint8_t * after_pc = z80_decode(pc, &inst); - z80_disasm(&inst, input_buf, address); - printf("%X:\t%s\n", address, input_buf); - uint16_t after = address + (after_pc-pc); - int debugging = 1; - while(debugging) { - fputs(">", stdout); - if (!fgets(input_buf, sizeof(input_buf), stdin)) { - fputs("fgets failed", stderr); - break; - } - strip_nl(input_buf); - //hitting enter repeats last command - if (input_buf[0]) { - strcpy(last_cmd, input_buf); - } else { - strcpy(input_buf, last_cmd); - } - char * param; - char format[8]; - uint32_t value; - bp_def * new_bp; - switch(input_buf[0]) - { - case 'a': - param = find_param(input_buf); - if (!param) { - fputs("a command requires a parameter\n", stderr); - break; - } - value = strtol(param, NULL, 16); - zinsert_breakpoint(context, value, (uint8_t *)zdebugger); - debugging = 0; - break; - case 'b': - param = find_param(input_buf); - if (!param) { - fputs("b command requires a parameter\n", stderr); - break; - } - value = strtol(param, NULL, 16); - zinsert_breakpoint(context, value, (uint8_t *)zdebugger); - new_bp = malloc(sizeof(bp_def)); - new_bp->next = zbreakpoints; - new_bp->address = value; - new_bp->index = zbp_index++; - new_bp->commands = NULL; - zbreakpoints = new_bp; - printf("Z80 Breakpoint %d set at %X\n", new_bp->index, value); - break; - case 'c': - puts("Continuing"); - debugging = 0; - break; - case 'd': - if (input_buf[1] == 'i') { - char format_char = 0; - for(int i = 2; input_buf[i] != 0 && input_buf[i] != ' '; i++) { - if (input_buf[i] == '/') { - format_char = input_buf[i+1]; - break; - } - } - param = find_param(input_buf); - if (!param) { - fputs("display command requires a parameter\n", stderr); - break; - } - zdebugger_print(context, format_char, param); - add_display(&zdisplays, &zdisp_index, format_char, param); - } else if (input_buf[1] == 'e' || input_buf[1] == ' ') { - param = find_param(input_buf); - if (!param) { - fputs("delete command requires a parameter\n", stderr); - break; - } - if (param[0] >= '0' && param[0] <= '9') { - value = atoi(param); - this_bp = find_breakpoint_idx(&zbreakpoints, value); - if (!*this_bp) { - fprintf(stderr, "Breakpoint %d does not exist\n", value); - break; - } - new_bp = *this_bp; - zremove_breakpoint(context, new_bp->address); - *this_bp = new_bp->next; - free(new_bp); - } else if (param[0] == 'd') { - param = find_param(param); - if (!param) { - fputs("delete display command requires a parameter\n", stderr); - break; - } - remove_display(&zdisplays, atoi(param)); - } - } - break; - case 'n': - //TODO: Handle conditional branch instructions - if (inst.op == Z80_JP) { - if (inst.addr_mode == Z80_IMMED) { - after = inst.immed; - } else if (inst.ea_reg == Z80_HL) { -#ifndef NEW_CORE - after = context->regs[Z80_H] << 8 | context->regs[Z80_L]; - } else if (inst.ea_reg == Z80_IX) { - after = context->regs[Z80_IXH] << 8 | context->regs[Z80_IXL]; - } else if (inst.ea_reg == Z80_IY) { - after = context->regs[Z80_IYH] << 8 | context->regs[Z80_IYL]; -#endif - } - } else if(inst.op == Z80_JR) { - after += inst.immed; - } else if(inst.op == Z80_RET) { - uint8_t *sp = get_native_pointer(context->sp, (void **)context->mem_pointers, &context->Z80_OPTS->gen); - if (sp) { - after = *sp; - sp = get_native_pointer((context->sp + 1) & 0xFFFF, (void **)context->mem_pointers, &context->Z80_OPTS->gen); - if (sp) { - after |= *sp << 8; - } - } - } - zinsert_breakpoint(context, after, (uint8_t *)zdebugger); - debugging = 0; - break; - case 'p': - param = find_param(input_buf); - if (!param) { - fputs("p command requires a parameter\n", stderr); - break; - } - zdebugger_print(context, input_buf[1] == '/' ? input_buf[2] : 0, param); - break; - case 'q': - puts("Quitting"); - exit(0); - break; - case 's': { - param = find_param(input_buf); - if (!param) { - fputs("s command requires a file name\n", stderr); - break; - } - memmap_chunk const *ram_chunk = NULL; - for (int i = 0; i < context->Z80_OPTS->gen.memmap_chunks; i++) - { - memmap_chunk const *cur = context->Z80_OPTS->gen.memmap + i; - if (cur->flags & MMAP_WRITE) { - ram_chunk = cur; - break; - } - } - if (ram_chunk) { - uint32_t size = ram_chunk->end - ram_chunk->start; - if (size > ram_chunk->mask) { - size = ram_chunk->mask+1; - } - uint8_t *buf = get_native_pointer(ram_chunk->start, (void **)context->mem_pointers, &context->Z80_OPTS->gen); - FILE * f = fopen(param, "wb"); - if (f) { - if(fwrite(buf, 1, size, f) != size) { - fputs("Error writing file\n", stderr); - } - fclose(f); - printf("Wrote %d bytes to %s\n", size, param); - } else { - fprintf(stderr, "Could not open %s for writing\n", param); - } - } else { - fputs("Failed to find a RAM memory chunk\n", stderr); - } - break; - } - case '?': - print_z80_help(); - break; - default: - if ( - !context->Z80_OPTS->gen.debug_cmd_handler - || !context->Z80_OPTS->gen.debug_cmd_handler(&system->header, input_buf) - ) { - fprintf(stderr, "Unrecognized debugger command %s\nUse '?' for help.\n", input_buf); - } - break; - } - } return context; } #endif -static uint32_t branch_t; -static uint32_t branch_f; - -int run_debugger_command(m68k_context *context, uint32_t address, char *input_buf, m68kinst inst, uint32_t after) -{ - char * param; - char format_char; - genesis_context *system = context->system; - uint32_t value; - bp_def *new_bp, **this_bp; - switch(input_buf[0]) - { - case 'c': - if (input_buf[1] == 0 || input_buf[1] == 'o' && input_buf[2] == 'n') - { - puts("Continuing"); - return 0; - } else if (input_buf[1] == 'o' && input_buf[2] == 'm') { - param = find_param(input_buf); - if (!param) { - fputs("com command requires a parameter\n", stderr); - break; - } - bp_def **target = find_breakpoint_idx(&breakpoints, atoi(param)); - if (!target) { - fprintf(stderr, "Breakpoint %s does not exist!\n", param); - break; - } - printf("Enter commands for breakpoing %d, type end when done\n", atoi(param)); - char cmd_buf[1024]; - char *commands = NULL; - for (;;) - { - fputs(">>", stdout); - fflush(stdout); - fgets(cmd_buf, sizeof(cmd_buf), stdin); - if (strcmp(cmd_buf, "end\n")) { - if (commands) { - char *tmp = commands; - commands = alloc_concat(commands, cmd_buf); - free(tmp); - } else { - commands = strdup(cmd_buf); - } - } else { - break; - } - } - (*target)->commands = commands; - } else { - } - break; - case 'b': - if (input_buf[1] == 't') { - uint32_t stack = context->aregs[7]; - if (stack >= 0xE00000) { - stack &= 0xFFFF; - uint8_t non_adr_count = 0; - do { - uint32_t bt_address = system->work_ram[stack/2] << 16 | system->work_ram[stack/2+1]; - bt_address = get_instruction_start(context->options, bt_address - 2); - if (bt_address) { - stack += 4; - non_adr_count = 0; - uint16_t *bt_pc = NULL; - if (bt_address < 0x400000) { - bt_pc = system->cart + bt_address/2; - } else if(bt_address > 0xE00000) { - bt_pc = system->work_ram + (bt_address & 0xFFFF)/2; - } - m68k_decode(bt_pc, &inst, bt_address); - m68k_disasm(&inst, input_buf); - printf("%X: %s\n", bt_address, input_buf); - } else { - //non-return address value on stack can be word wide - stack += 2; - non_adr_count++; - } - stack &= 0xFFFF; - } while (stack && non_adr_count < 6); - } - } else { - param = find_param(input_buf); - if (!param) { - fputs("b command requires a parameter\n", stderr); - break; - } - value = strtol(param, NULL, 16); - insert_breakpoint(context, value, debugger); - new_bp = malloc(sizeof(bp_def)); - new_bp->next = breakpoints; - new_bp->address = value; - new_bp->index = bp_index++; - new_bp->commands = NULL; - breakpoints = new_bp; - printf("68K Breakpoint %d set at %X\n", new_bp->index, value); - } - break; - case 'a': - param = find_param(input_buf); - if (!param) { - fputs("a command requires a parameter\n", stderr); - break; - } - value = strtol(param, NULL, 16); - insert_breakpoint(context, value, debugger); - return 0; - case 'd': - if (input_buf[1] == 'i') { - format_char = 0; - for(int i = 2; input_buf[i] != 0 && input_buf[i] != ' '; i++) { - if (input_buf[i] == '/') { - format_char = input_buf[i+1]; - break; - } - } - param = find_param(input_buf); - if (!param) { - fputs("display command requires a parameter\n", stderr); - break; - } - debugger_print(context, format_char, param, address); - add_display(&displays, &disp_index, format_char, param); - } else { - param = find_param(input_buf); - if (!param) { - fputs("d command requires a parameter\n", stderr); - break; - } - value = atoi(param); - this_bp = find_breakpoint_idx(&breakpoints, value); - if (!*this_bp) { - fprintf(stderr, "Breakpoint %d does not exist\n", value); - break; - } - new_bp = *this_bp; - *this_bp = (*this_bp)->next; - if (new_bp->commands) { - free(new_bp->commands); - } - free(new_bp); - } - break; - case 'p': - format_char = 0; - for(int i = 1; input_buf[i] != 0 && input_buf[i] != ' '; i++) { - if (input_buf[i] == '/') { - format_char = input_buf[i+1]; - break; - } - } - param = find_param(input_buf); - if (param) { - debugger_print(context, format_char, param, address); - } else { - m68k_disasm(&inst, input_buf); - printf("%X: %s\n", address, input_buf); - } - - break; - case 'n': - if (inst.op == M68K_RTS) { - after = m68k_read_long(context->aregs[7], context); - } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) { - after = m68k_read_long(context->aregs[7] + 2, context); - } else if(m68k_is_noncall_branch(&inst)) { - if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) { - branch_f = after; - branch_t = m68k_branch_target(&inst, context->dregs, context->aregs); - insert_breakpoint(context, branch_t, debugger); - } else if(inst.op == M68K_DBCC) { - if ( inst.extra.cond == COND_FALSE) { - if (context->dregs[inst.dst.params.regs.pri] & 0xFFFF) { - after = m68k_branch_target(&inst, context->dregs, context->aregs); - } - } else { - branch_t = after; - branch_f = m68k_branch_target(&inst, context->dregs, context->aregs); - insert_breakpoint(context, branch_f, debugger); - } - } else { - after = m68k_branch_target(&inst, context->dregs, context->aregs); - } - } - insert_breakpoint(context, after, debugger); - return 0; - case 'o': - if (inst.op == M68K_RTS) { - after = m68k_read_long(context->aregs[7], context); - } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) { - after = m68k_read_long(context->aregs[7] + 2, context); - } else if(m68k_is_noncall_branch(&inst)) { - if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) { - branch_t = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF; - if (branch_t < after) { - branch_t = 0; - } else { - branch_f = after; - insert_breakpoint(context, branch_t, debugger); - } - } else if(inst.op == M68K_DBCC) { - uint32_t target = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF; - if (target > after) { - if (inst.extra.cond == COND_FALSE) { - after = target; - } else { - branch_f = target; - branch_t = after; - insert_breakpoint(context, branch_f, debugger); - } - } - } else { - after = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF; - } - } - insert_breakpoint(context, after, debugger); - return 0; - case 's': - if (input_buf[1] == 'e') { - param = find_param(input_buf); - if (!param) { - fputs("Missing destination parameter for set\n", stderr); - return 1; - } - char *val = find_param(param); - if (!val) { - fputs("Missing value parameter for set\n", stderr); - return 1; - } - long int_val; - int reg_num; - switch (val[0]) - { - case 'd': - case 'a': - reg_num = val[1] - '0'; - if (reg_num < 0 || reg_num > 8) { - fprintf(stderr, "Invalid register %s\n", val); - return 1; - } - int_val = (val[0] == 'd' ? context->dregs : context->aregs)[reg_num]; - break; - case '$': - int_val = strtol(val+1, NULL, 16); - break; - case '0': - if (val[1] == 'x') { - int_val = strtol(val+2, NULL, 16); - break; - } - default: - int_val = strtol(val, NULL, 10); - } - switch(param[0]) - { - case 'd': - case 'a': - reg_num = param[1] - '0'; - if (reg_num < 0 || reg_num > 8) { - fprintf(stderr, "Invalid register %s\n", param); - return 1; - } - (param[0] == 'd' ? context->dregs : context->aregs)[reg_num] = int_val; - break; - default: - fprintf(stderr, "Invalid destinatino %s\n", param); - } - break; - } else if (input_buf[1] == 'r') { - system->header.soft_reset(&system->header); - return 0; - } else { - if (inst.op == M68K_RTS) { - after = m68k_read_long(context->aregs[7], context); - } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) { - after = m68k_read_long(context->aregs[7] + 2, context); - } else if(m68k_is_branch(&inst)) { - if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) { - branch_f = after; - branch_t = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF; - insert_breakpoint(context, branch_t, debugger); - } else if(inst.op == M68K_DBCC) { - if (inst.extra.cond == COND_FALSE) { - if (context->dregs[inst.dst.params.regs.pri] & 0xFFFF) { - after = m68k_branch_target(&inst, context->dregs, context->aregs); - } - } else { - branch_t = after; - branch_f = m68k_branch_target(&inst, context->dregs, context->aregs); - insert_breakpoint(context, branch_f, debugger); - } - } else { - after = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF; - } - } - insert_breakpoint(context, after, debugger); - return 0; - } - case 'v': { - genesis_context * gen = context->system; - //VDP debug commands - switch(input_buf[1]) - { - case 's': - vdp_print_sprite_table(gen->vdp); - break; - case 'r': - vdp_print_reg_explain(gen->vdp); - break; - } - break; - } - case 'y': { - genesis_context * gen = context->system; - //YM-2612 debug commands - switch(input_buf[1]) - { - case 'c': - if (input_buf[2] == ' ') { - int channel = atoi(input_buf+3)-1; - ym_print_channel_info(gen->ym, channel); - } else { - for (int i = 0; i < 6; i++) { - ym_print_channel_info(gen->ym, i); - } - } - break; - case 't': - ym_print_timer_info(gen->ym); - break; - } - break; - } -#ifndef NO_Z80 - case 'z': { - genesis_context * gen = context->system; - //Z80 debug commands - switch(input_buf[1]) - { - case 'b': - param = find_param(input_buf); - if (!param) { - fputs("zb command requires a parameter\n", stderr); - break; - } - value = strtol(param, NULL, 16); - zinsert_breakpoint(gen->z80, value, (uint8_t *)zdebugger); - new_bp = malloc(sizeof(bp_def)); - new_bp->next = zbreakpoints; - new_bp->address = value; - new_bp->index = zbp_index++; - zbreakpoints = new_bp; - printf("Z80 Breakpoint %d set at %X\n", new_bp->index, value); - break; - case 'p': - param = find_param(input_buf); - if (!param) { - fputs("zp command requires a parameter\n", stderr); - break; - } - zdebugger_print(gen->z80, input_buf[2] == '/' ? input_buf[3] : 0, param); - } - break; - } -#endif - case '?': - print_m68k_help(); - break; - case 'q': - puts("Quitting"); - exit(0); - break; - default: - fprintf(stderr, "Unrecognized debugger command %s\nUse '?' for help.\n", input_buf); - break; - } - return 1; -} - -void print_m68k_help() -{ - printf("M68k Debugger Commands\n"); - printf(" b ADDRESS - Set a breakpoint at ADDRESS\n"); - printf(" d BREAKPOINT - Delete a 68K breakpoint\n"); - printf(" co BREAKPOINT - Run a list of debugger commands each time\n"); - printf(" BREAKPOINT is hit\n"); - printf(" a ADDRESS - Advance to address\n"); - printf(" n - Advance to next instruction\n"); - printf(" o - Advance to next instruction ignoring branches to\n"); - printf(" lower addresses (good for breaking out of loops)\n"); - printf(" s - Advance to next instruction (follows bsr/jsr)\n"); - printf(" se REG|ADDRESS VALUE - Set value\n"); - printf(" sr - Soft reset\n"); - printf(" c - Continue\n"); - printf(" bt - Print a backtrace\n"); - printf(" p[/(x|X|d|c)] VALUE - Print a register or memory location\n"); - printf(" di[/(x|X|d|c)] VALUE - Print a register or memory location each time\n"); - printf(" a breakpoint is hit\n"); - printf(" vs - Print VDP sprite list\n"); - printf(" vr - Print VDP register info\n"); - printf(" yc [CHANNEL NUM] - Print YM-2612 channel info\n"); - printf(" yt - Print YM-2612 timer info\n"); - printf(" zb ADDRESS - Set a Z80 breakpoint\n"); - printf(" zp[/(x|X|d|c)] VALUE - Display a Z80 value\n"); - printf(" ? - Display help\n"); - printf(" q - Quit BlastEm\n"); -} - -void print_z80_help() -{ - printf("Z80 Debugger Commands\n"); - printf(" b ADDRESS - Set a breakpoint at ADDRESS\n"); - printf(" de BREAKPOINT - Delete a Z80 breakpoint\n"); - printf(" a ADDRESS - Advance to address\n"); - printf(" n - Advance to next instruction\n"); - printf(" c - Continue\n"); - printf(" p[/(x|X|d|c)] VALUE - Print a register or memory location\n"); - printf(" di[/(x|X|d|c)] VALUE - Print a register or memory location each time\n"); - printf(" a breakpoint is hit\n"); - printf(" q - Quit BlastEm\n"); -} - void debugger(m68k_context * context, uint32_t address) { - static char last_cmd[1024]; - char input_buf[1024]; - m68kinst inst; - - init_terminal(); - - sync_components(context, 0); - genesis_context *gen = context->system; - vdp_force_update_framebuffer(gen->vdp); - //probably not necessary, but let's play it safe - address &= 0xFFFFFF; - if (address == branch_t) { - bp_def ** f_bp = find_breakpoint(&breakpoints, branch_f); - if (!*f_bp) { - remove_breakpoint(context, branch_f); - } - branch_t = branch_f = 0; - } else if(address == branch_f) { - bp_def ** t_bp = find_breakpoint(&breakpoints, branch_t); - if (!*t_bp) { - remove_breakpoint(context, branch_t); - } - branch_t = branch_f = 0; - } - - uint16_t * pc = get_native_pointer(address, (void **)context->mem_pointers, &context->options->gen); - if (!pc) { - fatal_error("Entered 68K debugger at address %X\n", address); - } - uint16_t * after_pc = m68k_decode(pc, &inst, address); - uint32_t after = address + (after_pc-pc)*2; - int debugging = 1; - //Check if this is a user set breakpoint, or just a temporary one - bp_def ** this_bp = find_breakpoint(&breakpoints, address); - if (*this_bp) { - - if ((*this_bp)->commands) - { - char *commands = strdup((*this_bp)->commands); - char *copy = commands; - - while (debugging && *commands) - { - char *cmd = commands; - strip_nl(cmd); - commands += strlen(cmd) + 1; - debugging = run_debugger_command(context, address, cmd, inst, after); - } - free(copy); - } - if (debugging) { - printf("68K Breakpoint %d hit\n", (*this_bp)->index); - } else { - return; - } - } else { - remove_breakpoint(context, address); - } - for (disp_def * cur = displays; cur; cur = cur->next) { - debugger_print(context, cur->format_char, cur->param, address); - } - m68k_disasm(&inst, input_buf); - printf("%X: %s\n", address, input_buf); -#ifdef _WIN32 -#define prompt 1 -#else - int prompt = 1; - fd_set read_fds; - FD_ZERO(&read_fds); - struct timeval timeout; -#endif - while (debugging) { - if (prompt) { - fputs(">", stdout); - fflush(stdout); - } - process_events(); -#ifndef _WIN32 - timeout.tv_sec = 0; - timeout.tv_usec = 16667; - FD_SET(fileno(stdin), &read_fds); - if(select(fileno(stdin) + 1, &read_fds, NULL, NULL, &timeout) < 1) { - prompt = 0; - continue; - } else { - prompt = 1; - } -#endif - if (!fgets(input_buf, sizeof(input_buf), stdin)) { - fputs("fgets failed", stderr); - break; - } - strip_nl(input_buf); - //hitting enter repeats last command - if (input_buf[0]) { - strcpy(last_cmd, input_buf); - } else { - strcpy(input_buf, last_cmd); - } - debugging = run_debugger_command(context, address, input_buf, inst, after); - } return; } diff -r 804954731e3f -r b119e0de9a70 megawifi.c --- a/megawifi.c Thu Aug 05 23:48:41 2021 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,834 +0,0 @@ -#include -#include -#include -#include -#ifdef _WIN32 -#define WINVER 0x501 -#include -#include -#include -#else -#include -#include -#include -#include -#include -#endif -#include -#include -#include -#include "genesis.h" -#include "net.h" -#include "util.h" - -#if defined(_WIN32) || defined(__APPLE__) -# if BYTE_ORDER == LITTLE_ENDIAN -#define htobe64(val) ((((uint64_t)htonl((val)&0xFFFFFFFF))<<32) | htonl((val)>>32)) -# else -#define htobe64(val) (val) -# endif -#endif - -enum { - TX_IDLE, - TX_LEN1, - TX_LEN2, - TX_PAYLOAD, - TX_WAIT_ETX -}; -#define STX 0x7E -#define ETX 0x7E -#define MAX_RECV_SIZE 1460 - -#define E(N) N -enum { -#include "mw_commands.c" - CMD_ERROR = 255 -}; -#undef E -#define E(N) #N -static const char *cmd_names[] = { -#include "mw_commands.c" - [255] = "CMD_ERROR" -}; - -#ifndef MSG_NOSIGNAL -#define MSG_NOSIGNAL 0 -#endif - -enum mw_state { - STATE_IDLE=1, - STATE_AP_JOIN, - STATE_SCAN, - STATE_READY, - STATE_TRANSPARENT -}; - -enum { - SOCKST_NONE = 0, - SOCKST_TCP_LISTEN, - SOCKST_TCP_EST, - SOCKST_UDP_READY -}; - -// TCP/UDP address message -struct mw_addr_msg { - char dst_port[6]; - char src_port[6]; - uint8_t channel; - char host[]; -}; - -#define FLAG_ONLINE - -typedef struct { - uint32_t transmit_bytes; - uint32_t expected_bytes; - uint32_t receive_bytes; - uint32_t receive_read; - int sock_fds[15]; - uint16_t channel_flags; - uint8_t channel_state[15]; - uint8_t scratchpad; - uint8_t transmit_channel; - uint8_t transmit_state; - uint8_t module_state; - uint8_t flags; - uint8_t transmit_buffer[4096]; - uint8_t receive_buffer[4096]; - struct sockaddr_in remote_addr[15]; // Needed for UDP sockets -} megawifi; - -static megawifi *get_megawifi(void *context) -{ - m68k_context *m68k = context; - genesis_context *gen = m68k->system; - if (!gen->extra) { - socket_init(); - gen->extra = calloc(1, sizeof(megawifi)); - megawifi *mw = gen->extra; - mw->module_state = STATE_IDLE; - mw->flags = 0xE0; // cfg_ok, dt_ok, online - for (int i = 0; i < 15; i++) { - mw->sock_fds[i] = -1; - } - } - return gen->extra; -} - -static void mw_putc(megawifi *mw, uint8_t v) -{ - if (mw->receive_bytes == sizeof(mw->receive_buffer)) { - return; - } - mw->receive_buffer[mw->receive_bytes++] = v; -} - -static void mw_set(megawifi *mw, uint8_t val, uint32_t count) -{ - if (count + mw->receive_bytes > sizeof(mw->receive_buffer)) { - count = sizeof(mw->receive_buffer) - mw->receive_bytes; - } - memset(mw->receive_buffer + mw->receive_bytes, val, count); - mw->receive_bytes += count; -} - -static void mw_copy(megawifi *mw, const uint8_t *src, uint32_t count) -{ - if (count + mw->receive_bytes > sizeof(mw->receive_buffer)) { - count = sizeof(mw->receive_buffer) - mw->receive_bytes; - } - memcpy(mw->receive_buffer + mw->receive_bytes, src, count); - mw->receive_bytes += count; -} - -static void mw_puts(megawifi *mw, const char *s) -{ - size_t len = strlen(s); - mw_copy(mw, (uint8_t*)s, len); -} - -static void udp_recv(megawifi *mw, uint8_t idx) -{ - ssize_t recvd; - int s = mw->sock_fds[idx]; - struct sockaddr_in remote; - socklen_t addr_len = sizeof(struct sockaddr_in); - - if (mw->remote_addr[idx].sin_addr.s_addr != htonl(INADDR_ANY)) { - // Receive only from specified address - recvd = recvfrom(s, (char*)mw->receive_buffer + 3, MAX_RECV_SIZE, 0, - (struct sockaddr*)&remote, &addr_len); - if (recvd > 0) { - if (remote.sin_addr.s_addr != mw->remote_addr[idx].sin_addr.s_addr) { - printf("Discarding UDP packet from unknown addr %s:%d\n", - inet_ntoa(remote.sin_addr), ntohs(remote.sin_port)); - recvd = 0; - } - } - } else { - // Reuse mode, data is preceded by remote IPv4 and port - recvd = recvfrom(s, (char*)mw->receive_buffer + 9, MAX_RECV_SIZE - 6, - 0, (struct sockaddr*)&remote, &addr_len); - if (recvd > 0) { - mw->receive_buffer[3] = remote.sin_addr.s_addr; - mw->receive_buffer[4] = remote.sin_addr.s_addr>>8; - mw->receive_buffer[5] = remote.sin_addr.s_addr>>16; - mw->receive_buffer[6] = remote.sin_addr.s_addr>>24; - mw->receive_buffer[7] = remote.sin_port; - mw->receive_buffer[8] = remote.sin_port>>8; - recvd += 6; - } - } - - if (recvd > 0) { - mw_putc(mw, STX); - mw_putc(mw, (recvd >> 8) | ((idx+1) << 4)); - mw_putc(mw, recvd); - mw->receive_bytes += recvd; - mw_putc(mw, ETX); - //should this set the channel flag? - } else if (recvd < 0 && !socket_error_is_wouldblock()) { - socket_close(mw->sock_fds[idx]); - mw->channel_state[idx] = SOCKST_NONE; - mw->channel_flags |= 1 << (idx + 1); - } -} - -static void udp_send(megawifi *mw, uint8_t idx) -{ - struct sockaddr_in remote; - int s = mw->sock_fds[idx]; - int sent; - char *data = (char*)mw->transmit_buffer; - - if (mw->remote_addr[idx].sin_addr.s_addr != htonl(INADDR_ANY)) { - sent = sendto(s, data, mw->transmit_bytes, 0, (struct sockaddr*)&mw->remote_addr[idx], - sizeof(struct sockaddr_in)); - } else { - // Reuse mode, extract address from leading bytes - // NOTE: mw->remote_addr[idx].sin_addr.s_addr == INADDR_ANY - remote.sin_addr.s_addr = *((int32_t*)data); - remote.sin_port = *((int16_t*)(data + 4)); - remote.sin_family = AF_INET; - memset(remote.sin_zero, 0, sizeof(remote.sin_zero)); - sent = sendto(s, data + 6, mw->transmit_bytes - 6, 0, (struct sockaddr*)&remote, - sizeof(struct sockaddr_in)) + 6; - } - if (sent < 0 && !socket_error_is_wouldblock()) { - socket_close(s); - mw->sock_fds[idx] = -1; - mw->channel_state[idx] = SOCKST_NONE; - mw->channel_flags |= 1 << (idx + 1); - } else if (sent < mw->transmit_bytes) { - //TODO: save this data somewhere so it can be sent in poll_socket - printf("Sent %d bytes on channel %d, but %d were requested\n", sent, idx + 1, mw->transmit_bytes); - } -} - -static void poll_socket(megawifi *mw, uint8_t channel) -{ - if (mw->sock_fds[channel] < 0) { - return; - } - if (mw->channel_state[channel] == SOCKST_TCP_LISTEN) { - int res = accept(mw->sock_fds[channel], NULL, NULL); - if (res >= 0) { - socket_close(mw->sock_fds[channel]); - socket_blocking(res, 0); - mw->sock_fds[channel] = res; - mw->channel_state[channel] = SOCKST_TCP_EST; - mw->channel_flags |= 1 << (channel + 1); - } else if (errno != EAGAIN && errno != EWOULDBLOCK) { - socket_close(mw->sock_fds[channel]); - mw->channel_state[channel] = SOCKST_NONE; - mw->channel_flags |= 1 << (channel + 1); - } - } else if (mw->channel_state[channel] == SOCKST_TCP_EST && mw->receive_bytes < (sizeof(mw->receive_buffer) - 4)) { - size_t max = sizeof(mw->receive_buffer) - 4 - mw->receive_bytes; - if (max > MAX_RECV_SIZE) { - max = MAX_RECV_SIZE; - } - int bytes = recv(mw->sock_fds[channel], (char*)(mw->receive_buffer + mw->receive_bytes + 3), max, 0); - if (bytes > 0) { - mw_putc(mw, STX); - mw_putc(mw, bytes >> 8 | (channel+1) << 4); - mw_putc(mw, bytes); - mw->receive_bytes += bytes; - mw_putc(mw, ETX); - //should this set the channel flag? - } else if (bytes < 0 && !socket_error_is_wouldblock()) { - socket_close(mw->sock_fds[channel]); - mw->channel_state[channel] = SOCKST_NONE; - mw->channel_flags |= 1 << (channel + 1); - } - } else if (mw->channel_state[channel] == SOCKST_UDP_READY && !mw->receive_bytes) { - udp_recv(mw, channel); - } -} - -static void poll_all_sockets(megawifi *mw) -{ - for (int i = 0; i < 15; i++) - { - poll_socket(mw, i); - } -} - - -static void start_reply(megawifi *mw, uint8_t cmd) -{ - mw_putc(mw, STX); - //reserve space for length - mw->receive_bytes += 2; - //cmd - mw_putc(mw, 0); - mw_putc(mw, cmd); - //reserve space for length - mw->receive_bytes += 2; -} - -static void end_reply(megawifi *mw) -{ - uint32_t len = mw->receive_bytes - 3; - //LSD packet length - mw->receive_buffer[1] = len >> 8; - mw->receive_buffer[2] = len; - //command length - len -= 4; - mw->receive_buffer[5] = len >> 8; - mw->receive_buffer[6] = len; - mw_putc(mw, ETX); -} - -static void cmd_ap_cfg_get(megawifi *mw) -{ - char ssid[32] = {0}; - char pass[64] = {0}; - uint8_t slot = mw->transmit_buffer[4]; - - sprintf(ssid, "BLASTEM! SSID %d", slot + 1); - sprintf(pass, "BLASTEM! PASS %d", slot + 1); - start_reply(mw, CMD_OK); - mw_putc(mw, slot); - mw_putc(mw, 7); /// 11bgn - mw_copy(mw, (uint8_t*)ssid, 32); - mw_copy(mw, (uint8_t*)pass, 64); - end_reply(mw); -} - -static void cmd_ip_cfg_get(megawifi *mw) -{ - uint32_t ipv4s[5] = {0}; - - start_reply(mw, CMD_OK); - mw_putc(mw, mw->transmit_buffer[4]); - mw_putc(mw, 0); - mw_putc(mw, 0); - mw_putc(mw, 0); - mw_copy(mw, (uint8_t*)ipv4s, sizeof(ipv4s)); - end_reply(mw); -} - -static void cmd_tcp_con(megawifi *mw, uint32_t size) -{ - struct mw_addr_msg *addr = (struct mw_addr_msg*)(mw->transmit_buffer + 4); - struct addrinfo hints; - struct addrinfo *res = NULL; - int s; - int err; - - uint8_t channel = addr->channel; - if (!channel || channel > 15 || mw->sock_fds[channel - 1] >= 0) { - start_reply(mw, CMD_ERROR); - end_reply(mw); - return; - } - channel--; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; -#ifndef _WIN32 - hints.ai_flags = AI_NUMERICSERV; -#endif - hints.ai_socktype = SOCK_STREAM; - - if ((err = getaddrinfo(addr->host, addr->dst_port, &hints, &res)) != 0) { - printf("getaddrinfo failed: %s\n", gai_strerror(err)); - start_reply(mw, CMD_ERROR); - end_reply(mw); - return; - } - - s = socket(AF_INET, SOCK_STREAM, 0); - if (s < 0) { - goto err; - } - - // Should this be handled in a separate thread to avoid blocking emulation? - if (connect(s, res->ai_addr, res->ai_addrlen) != 0) { - goto err; - } - - socket_blocking(s, 0); - mw->sock_fds[channel] = s; - mw->channel_state[channel] = SOCKST_TCP_EST; - mw->channel_flags |= 1 << (channel + 1); - printf("Connection established on ch %d with %s:%s\n", channel + 1, - addr->host, addr->dst_port); - - if (res) { - freeaddrinfo(res); - } - start_reply(mw, CMD_OK); - end_reply(mw); - return; - -err: - freeaddrinfo(res); - printf("Connection to %s:%s failed, %s\n", addr->host, addr->dst_port, strerror(errno)); - start_reply(mw, CMD_ERROR); - end_reply(mw); -} - -static void cmd_close(megawifi *mw) -{ - int channel = mw->transmit_buffer[4] - 1; - - if (channel >= 15 || mw->sock_fds[channel] < 0) { - start_reply(mw, CMD_ERROR); - end_reply(mw); - return; - } - - socket_close(mw->sock_fds[channel]); - mw->sock_fds[channel] = -1; - mw->channel_state[channel] = SOCKST_NONE; - mw->channel_flags |= 1 << (channel + 1); - start_reply(mw, CMD_OK); - end_reply(mw); -} - -static void cmd_udp_set(megawifi *mw) -{ - struct mw_addr_msg *addr = (struct mw_addr_msg*)(mw->transmit_buffer + 4); - unsigned int local_port, remote_port; - int s; - struct addrinfo *raddr; - struct addrinfo hints; - struct sockaddr_in local; - int err; - - uint8_t channel = addr->channel; - if (!channel || channel > 15 || mw->sock_fds[channel - 1] >= 0) { - goto err; - } - channel--; - local_port = atoi(addr->src_port); - remote_port = atoi(addr->dst_port); - - if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { - printf("Datagram socket creation failed\n"); - goto err; - } - - memset(local.sin_zero, 0, sizeof(local.sin_zero)); - local.sin_family = AF_INET; - local.sin_addr.s_addr = htonl(INADDR_ANY); - local.sin_port = htons(local_port); - if (remote_port && addr->host[0]) { - // Communication with remote peer - printf("Set UDP ch %d, port %d to addr %s:%d\n", addr->channel, - local_port, addr->host, remote_port); - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; -#ifndef _WIN32 - hints.ai_flags = AI_NUMERICSERV; -#endif - hints.ai_socktype = SOCK_DGRAM; - - if ((err = getaddrinfo(addr->host, addr->dst_port, &hints, &raddr)) != 0) { - printf("getaddrinfo failed: %s\n", gai_strerror(err)); - goto err; - } - mw->remote_addr[channel] = *((struct sockaddr_in*)raddr->ai_addr); - freeaddrinfo(raddr); - } else if (local_port) { - // Server in reuse mode - printf("Set UDP ch %d, src port %d\n", addr->channel, local_port); - mw->remote_addr[channel] = local; - } else { - printf("Invalid UDP socket data\n"); - goto err; - } - - if (bind(s, (struct sockaddr*)&local, sizeof(struct sockaddr_in)) < 0) { - printf("bind to port %d failed\n", local_port); - goto err; - } - - socket_blocking(s, 0); - mw->sock_fds[channel] = s; - mw->channel_state[channel] = SOCKST_UDP_READY; - mw->channel_flags |= 1 << (channel + 1); - - start_reply(mw, CMD_OK); - end_reply(mw); - - return; - -err: - start_reply(mw, CMD_ERROR); - end_reply(mw); -} - -#define AVATAR_BYTES (32 * 48 / 2) -static void cmd_gamertag_get(megawifi *mw) -{ - uint32_t id = htonl(1); - char buf[AVATAR_BYTES]; - - start_reply(mw, CMD_OK); - // TODO Get items from config file - mw_copy(mw, (uint8_t*)&id, 4); - strncpy(buf, "doragasu on Blastem!", 32); - mw_copy(mw, (uint8_t*)buf, 32); - strncpy(buf, "My cool password", 32); - mw_copy(mw, (uint8_t*)buf, 32); - strncpy(buf, "All your WiFi are belong to me!", 32); - mw_copy(mw, (uint8_t*)buf, 32); - memset(buf, 0, 64); // Telegram token - mw_copy(mw, (uint8_t*)buf, 64); - mw_copy(mw, (uint8_t*)buf, AVATAR_BYTES); // Avatar tiles - mw_copy(mw, (uint8_t*)buf, 32); // Avatar palette - end_reply(mw); -} - -static void cmd_hrng_get(megawifi *mw) -{ - uint16_t len = (mw->transmit_buffer[4]<<8) + mw->transmit_buffer[5]; - if (len > (MAX_RECV_SIZE - 4)) { - start_reply(mw, CMD_ERROR); - end_reply(mw); - return; - } - // Pseudo-random, but who cares - start_reply(mw, CMD_OK); - srand(time(NULL)); - for (uint16_t i = 0; i < len; i++) { - mw_putc(mw, rand()); - } - end_reply(mw); -} - -static void cmd_datetime(megawifi *mw) -{ - start_reply(mw, CMD_OK); -#ifdef _WIN32 - __time64_t t = _time64(NULL); - int64_t t_be = htobe64(t); - mw_copy(mw, (uint8_t*)&t_be, sizeof(int64_t)); - mw_puts(mw, _ctime64(&t)); -#else - time_t t = time(NULL); - int64_t t_be = htobe64(t); - mw_copy(mw, (uint8_t*)&t_be, sizeof(int64_t)); - mw_puts(mw, ctime(&t)); -#endif - - mw_putc(mw, '\0'); - end_reply(mw); -} - -static void process_command(megawifi *mw) -{ - uint32_t command = mw->transmit_buffer[0] << 8 | mw->transmit_buffer[1]; - uint32_t size = mw->transmit_buffer[2] << 8 | mw->transmit_buffer[3]; - if (size > mw->transmit_bytes - 4) { - size = mw->transmit_bytes - 4; - } - int orig_receive_bytes = mw->receive_bytes; - switch (command) - { - case CMD_VERSION: - start_reply(mw, CMD_OK); - mw_putc(mw, 1); - mw_putc(mw, 3); - mw_putc(mw, 0); - mw_puts(mw, "blastem"); - mw_putc(mw, '\0'); - end_reply(mw); - break; - case CMD_ECHO: - mw->receive_bytes = mw->transmit_bytes; - memcpy(mw->receive_buffer, mw->transmit_buffer, mw->transmit_bytes); - break; - case CMD_AP_CFG_GET: - cmd_ap_cfg_get(mw); - break; - case CMD_IP_CURRENT: { - iface_info i; - if (get_host_address(&i)) { - start_reply(mw, CMD_OK); - //config number and reserved bytes - mw_set(mw, 0, 4); - //ip - mw_copy(mw, i.ip, sizeof(i.ip)); - //net mask - mw_copy(mw, i.net_mask, sizeof(i.net_mask)); - //gateway guess - mw_putc(mw, i.ip[0] & i.net_mask[0]); - mw_putc(mw, i.ip[1] & i.net_mask[1]); - mw_putc(mw, i.ip[2] & i.net_mask[2]); - mw_putc(mw, (i.ip[3] & i.net_mask[3]) + 1); - //dns - static const uint8_t localhost[] = {127,0,0,1}; - mw_copy(mw, localhost, sizeof(localhost)); - mw_copy(mw, localhost, sizeof(localhost)); - - } else { - start_reply(mw, CMD_ERROR); - } - end_reply(mw); - break; - } - case CMD_IP_CFG_GET: - cmd_ip_cfg_get(mw); - break; - case CMD_DEF_AP_CFG_GET: - start_reply(mw, CMD_OK); - mw_putc(mw, 0); - end_reply(mw); - break; - case CMD_AP_JOIN: - mw->module_state = STATE_READY; - start_reply(mw, CMD_OK); - end_reply(mw); - break; - case CMD_TCP_CON: - cmd_tcp_con(mw, size); - break; - case CMD_TCP_BIND:{ - if (size < 7){ - start_reply(mw, CMD_ERROR); - end_reply(mw); - break; - } - uint8_t channel = mw->transmit_buffer[10]; - if (!channel || channel > 15) { - start_reply(mw, CMD_ERROR); - end_reply(mw); - break; - } - channel--; - if (mw->sock_fds[channel] >= 0) { - socket_close(mw->sock_fds[channel]); - } - mw->sock_fds[channel] = socket(AF_INET, SOCK_STREAM, 0); - if (mw->sock_fds[channel] < 0) { - start_reply(mw, CMD_ERROR); - end_reply(mw); - break; - } - int value = 1; - setsockopt(mw->sock_fds[channel], SOL_SOCKET, SO_REUSEADDR, (char*)&value, sizeof(value)); - struct sockaddr_in bind_addr; - memset(&bind_addr, 0, sizeof(bind_addr)); - bind_addr.sin_family = AF_INET; - bind_addr.sin_port = htons(mw->transmit_buffer[8] << 8 | mw->transmit_buffer[9]); - if (bind(mw->sock_fds[channel], (struct sockaddr *)&bind_addr, sizeof(bind_addr)) != 0) { - socket_close(mw->sock_fds[channel]); - mw->sock_fds[channel] = -1; - start_reply(mw, CMD_ERROR); - end_reply(mw); - break; - } - int res = listen(mw->sock_fds[channel], 2); - start_reply(mw, res ? CMD_ERROR : CMD_OK); - if (res) { - socket_close(mw->sock_fds[channel]); - mw->sock_fds[channel] = -1; - } else { - mw->channel_flags |= 1 << (channel + 1); - mw->channel_state[channel] = SOCKST_TCP_LISTEN; - socket_blocking(mw->sock_fds[channel], 0); - } - end_reply(mw); - break; - } - case CMD_CLOSE: - cmd_close(mw); - break; - case CMD_UDP_SET: - cmd_udp_set(mw); - break; - case CMD_SOCK_STAT: { - uint8_t channel = mw->transmit_buffer[4]; - if (!channel || channel > 15) { - start_reply(mw, CMD_ERROR); - end_reply(mw); - break; - } - mw->channel_flags &= ~(1 << channel); - channel--; - poll_socket(mw, channel); - start_reply(mw, CMD_OK); - mw_putc(mw, mw->channel_state[channel]); - end_reply(mw); - break; - } - case CMD_DATETIME: - cmd_datetime(mw); - break; - case CMD_SYS_STAT: - poll_all_sockets(mw); - start_reply(mw, CMD_OK); - mw_putc(mw, mw->module_state); - mw_putc(mw, mw->flags); - mw_putc(mw, mw->channel_flags >> 8); - mw_putc(mw, mw->channel_flags); - end_reply(mw); - break; - case CMD_GAMERTAG_GET: - cmd_gamertag_get(mw); - break; - case CMD_LOG: - start_reply(mw, CMD_OK); - puts((char*)&mw->transmit_buffer[4]); - end_reply(mw); - break; - case CMD_HRNG_GET: - cmd_hrng_get(mw); - break; - case CMD_SERVER_URL_GET: - start_reply(mw, CMD_OK); - // FIXME: This should be get from config file - mw_puts(mw, "doragasu.com"); - mw_putc(mw,'\0'); - end_reply(mw); - break; - default: - printf("Unhandled MegaWiFi command %s(%d) with length %X\n", cmd_names[command], command, size); - break; - } -} - -static void process_packet(megawifi *mw) -{ - if (mw->transmit_channel == 0) { - process_command(mw); - } else { - uint8_t channel = mw->transmit_channel - 1; - int channel_state = mw->channel_state[channel]; - int sock_fd = mw->sock_fds[channel]; - if (sock_fd >= 0 && channel_state == SOCKST_TCP_EST) { - int sent = send(sock_fd, (char*)mw->transmit_buffer, mw->transmit_bytes, 0); - if (sent < 0 && !socket_error_is_wouldblock()) { - socket_close(sock_fd); - mw->sock_fds[channel] = -1; - mw->channel_state[channel] = SOCKST_NONE; - mw->channel_flags |= 1 << mw->transmit_channel; - } else if (sent < mw->transmit_bytes) { - //TODO: save this data somewhere so it can be sent in poll_socket - printf("Sent %d bytes on channel %d, but %d were requested\n", sent, mw->transmit_channel, mw->transmit_bytes); - } - } else if (sock_fd >= 0 && channel_state == SOCKST_UDP_READY) { - udp_send(mw, channel); - } else { - printf("Unhandled receive of MegaWiFi data on channel %d\n", mw->transmit_channel); - } - } - mw->transmit_bytes = mw->expected_bytes = 0; -} - -void *megawifi_write_b(uint32_t address, void *context, uint8_t value) -{ - if (!(address & 1)) { - return context; - } - megawifi *mw = get_megawifi(context); - address = address >> 1 & 7; - switch (address) - { - case 0: - switch (mw->transmit_state) - { - case TX_IDLE: - if (value == STX) { - mw->transmit_state = TX_LEN1; - } - break; - case TX_LEN1: - mw->transmit_channel = value >> 4; - mw->expected_bytes = value << 8 & 0xF00; - mw->transmit_state = TX_LEN2; - break; - case TX_LEN2: - mw->expected_bytes |= value; - mw->transmit_state = TX_PAYLOAD; - break; - case TX_PAYLOAD: - mw->transmit_buffer[mw->transmit_bytes++] = value; - if (mw->transmit_bytes == mw->expected_bytes) { - mw->transmit_state = TX_WAIT_ETX; - } - break; - case TX_WAIT_ETX: - if (value == ETX) { - mw->transmit_state = TX_IDLE; - process_packet(mw); - } - break; - } - break; - case 7: - mw->scratchpad = value; - break; - default: - printf("Unhandled write to MegaWiFi UART register %X: %X\n", address, value); - } - return context; -} - -void *megawifi_write_w(uint32_t address, void *context, uint16_t value) -{ - return megawifi_write_b(address | 1, context, value); -} - -uint8_t megawifi_read_b(uint32_t address, void *context) -{ - - if (!(address & 1)) { - return 0xFF; - } - megawifi *mw = get_megawifi(context); - address = address >> 1 & 7; - switch (address) - { - case 0: - poll_all_sockets(mw); - if (mw->receive_read < mw->receive_bytes) { - uint8_t ret = mw->receive_buffer[mw->receive_read++]; - if (mw->receive_read == mw->receive_bytes) { - mw->receive_read = mw->receive_bytes = 0; - } - return ret; - } - return 0xFF; - case 5: - poll_all_sockets(mw); - //line status - return 0x60 | (mw->receive_read < mw->receive_bytes); - case 7: - return mw->scratchpad; - default: - printf("Unhandled read from MegaWiFi UART register %X\n", address); - return 0xFF; - } -} - -uint16_t megawifi_read_w(uint32_t address, void *context) -{ - return 0xFF00 | megawifi_read_b(address | 1, context); -} diff -r 804954731e3f -r b119e0de9a70 megawifi.h --- a/megawifi.h Thu Aug 05 23:48:41 2021 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -#ifndef MEGAWIFI_H_ -#define MEGAWIFI_H_ - -void *megawifi_write_w(uint32_t address, void *context, uint16_t value); -void *megawifi_write_b(uint32_t address, void *context, uint8_t value); -uint16_t megawifi_read_w(uint32_t address, void *context); -uint8_t megawifi_read_b(uint32_t address, void *context); - -#endif //MEGAWIFI_H_ diff -r 804954731e3f -r b119e0de9a70 romdb.c --- a/romdb.c Thu Aug 05 23:48:41 2021 -0700 +++ b/romdb.c Tue Sep 21 23:17:34 2021 -0700 @@ -11,7 +11,6 @@ #include "nor.h" #include "sega_mapper.h" #include "multi_game.h" -#include "megawifi.h" #include "jcart.h" #include "blastem.h" @@ -298,46 +297,6 @@ info->map[8].write_16 = (write_16_fun)write_bank_reg_w; info->map[8].write_8 = (write_8_fun)write_bank_reg_b; return; - } else if(!memcmp("SEGA MEGAWIFI", rom + 0x100, strlen("SEGA MEGAWIFI"))) { - info->mapper_type = MAPPER_NONE; - info->map_chunks = base_chunks + 2; - info->map = malloc(sizeof(memmap_chunk) * info->map_chunks); - memset(info->map, 0, sizeof(memmap_chunk)*2); - memcpy(info->map+2, base_map, sizeof(memmap_chunk) * base_chunks); - info->save_size = 0x400000; - info->save_bus = RAM_FLAG_BOTH; - info->save_type = SAVE_NOR; - info->map[0].start = 0; - info->map[0].end = 0x400000; - info->map[0].mask = 0xFFFFFF; - info->map[0].write_16 = nor_flash_write_w; - info->map[0].write_8 = nor_flash_write_b; - info->map[0].read_16 = nor_flash_read_w; - info->map[0].read_8 = nor_flash_read_b; - info->map[0].flags = MMAP_READ_CODE | MMAP_CODE; - info->map[0].buffer = info->save_buffer = calloc(info->save_size, 1); - uint32_t init_size = size < info->save_size ? size : info->save_size; - memcpy(info->save_buffer, rom, init_size); - byteswap_rom(info->save_size, (uint16_t *)info->save_buffer); - info->nor = calloc(1, sizeof(nor_state)); - nor_flash_init(info->nor, info->save_buffer, info->save_size, 128, 0xDA45, RAM_FLAG_BOTH); - info->nor->cmd_address1 = 0xAAB; - info->nor->cmd_address2 = 0x555; - info->map[1].start = 0xA130C0; - info->map[1].end = 0xA130D0; - info->map[1].mask = 0xFFFFFF; - if (!strcmp( - "on", - tern_find_path_default(config, "system\0megawifi\0", (tern_val){.ptrval="off"}, TVAL_PTR).ptrval) - ) { - info->map[1].write_16 = megawifi_write_w; - info->map[1].write_8 = megawifi_write_b; - info->map[1].read_16 = megawifi_read_w; - info->map[1].read_8 = megawifi_read_b; - } else { - warning("ROM uses MegaWiFi, but it is disabled\n"); - } - return; } else if (has_ram_header(rom, size)) { uint32_t ram_start = read_ram_header(info, rom); @@ -866,20 +825,6 @@ map->mask = 0xFF; map->write_16 = write_multi_game_w; map->write_8 = write_multi_game_b; - } else if (!strcmp(dtype, "megawifi")) { - if (!strcmp( - "on", - tern_find_path_default(config, "system\0megawifi\0", (tern_val){.ptrval="off"}, TVAL_PTR).ptrval) - ) { - map->write_16 = megawifi_write_w; - map->write_8 = megawifi_write_b; - map->read_16 = megawifi_read_w; - map->read_8 = megawifi_read_b; - map->mask = 0xFFFFFF; - } else { - warning("ROM uses MegaWiFi, but it is disabled\n"); - return; - } } else if (!strcmp(dtype, "jcart")) { state->info->mapper_type = MAPPER_JCART; map->write_16 = jcart_write_w;