Commit 65e40bbe authored by PoroCYon's avatar PoroCYon
Browse files

EEPROM restore, run code on walker from SD, dump code from in-cart IR mcu

parent 11ca682d
/*
* Copyright (c) 2020 PoroCYon <porocyon@titandemo.org>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef IR_H_
#define IR_H_
......@@ -39,8 +23,15 @@ enum ir_extra {
ir_extra_addrhi = 0x80
};
// receive from IR
size_t ir_cmd1(uint8_t* rxbuf /* either at least size 256, or NULL! */);
// send over IR
void ir_cmd2(size_t size, const uint8_t* txbuf);
// read byte at address from in-cartridge CPU
uint8_t ir_cmd4(uint16_t addr);
// TODO: cmd3: write byte to in-cart CPU
// cmd5,6: write/read word to/from in-cart CPU
// cmd7: "?"
uint8_t ir_cmd8(void);
inline static uint16_t ir_stat(void) {
......
/*
* Copyright (c) 2020 PoroCYon <porocyon@titandemo.org>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef PW_H_
#define PW_H_
......@@ -44,6 +28,10 @@ enum pw_cmdtype {
pw_cmd_geninf_req = 0x20,
pw_cmd_geninf_res = 0x22,
pw_cmd_eepwrite_align_req = 0x02,
pw_cmd_eepwrite_res = 0x04,
pw_cmd_eepwrite_req = 0x0a,
pw_cmd_memwrite_req = 0x06,
pw_cmd_memwrite_res = 0x06,
......@@ -104,6 +92,7 @@ bool pw_get_geninfo(uint32_t sessid, struct pw_geninfo* geninf);
bool pw_write_mem(uint32_t sessid, uint16_t addr, size_t size, const uint8_t* data); // 0x06
bool pw_read_eeprom(uint32_t sessid, uint16_t addr, size_t size, uint8_t* dest);
bool pw_write_eeprom(uint32_t sessid, uint16_t addr, size_t size, const uint8_t* src);
// NOTE: does ASCII only!
char pw_charconv_w2a(uint16_t wch);
......
......@@ -7,8 +7,6 @@
* (high level functions)
*
* Copyright (C) Pokedoc (2010)
*
* With back-to-C porting and slight modifications by PoroCYon (2020)
*/
/*
* This program is free software; you can redistribute it and/or modify
......
/*
* Copyright (c) 2020 PoroCYon <porocyon@titandemo.org>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
......@@ -127,6 +111,16 @@ void ir_cmd2(size_t size, const uint8_t* buf) {
auxspi_xfer_ir(buf[i], i < size-1);
}
}
uint8_t ir_cmd4(uint16_t addr) {
auxspi_xfer_ir(0x04, true);
auxspi_xfer_ir(addr >> 8, true);
auxspi_xfer_ir(addr & 0xff, true);
return auxspi_xfer_ir(0x00, false);
}
uint8_t ir_cmd8(void) {
auxspi_xfer_ir(0x08, true);
return auxspi_xfer_ir(0x00, false);
......
/*
* Copyright (c) 2020 PoroCYon <porocyon@titandemo.org>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
......@@ -35,26 +19,26 @@ static const uint8_t rom_dump_sploit[] = { // write to 0xf956
0x5e,0x00,0x25,0x9e, // jsr wdt_pet
0x5e,0x00,0x7b,0x64, // jsr smallDelay
0x5e,0x00,0x25,0x9e, // jsr wdt_pet
0x19,0x55, // sub.w r5, r5
0x19,0x55, // sub.w r5, r5 // memcpy source
//big_loop:
0x79,0x06,0xf8,0xd6, // mov.w 0xf8d6, r6 // packet payload buffer
0xfc,0x80, // mov.b 0x80, r4l // ???
0x7b,0x5c,0x59,0x8f, // eemov.b
0x79,0x06,0xf8,0xd6, // mov.w 0xf8d6, r6 // memcpy dest: packet payload buffer
0xfc,0x80, // mov.b 0x80, r4l // memcpy length
0x7b,0x5c,0x59,0x8f, // eemov.b // memcpy
0x79,0x00,0x3c,0x80, // mov.w 0x3c80, r0 // payload len=80h, cmd=3ch
0x5e,0x00,0x07,0x72, // jsr sendPacket
0x5e,0x00,0x7b,0x64, // jsr smallDelay
0x5e,0x00,0x25,0x9e, // jsr wdt_pet
0x5e,0x00,0x7b,0x64, // jsr smallDelay
0x79,0x25,0xc0,0x00, // cmp.w r5, 0xc000
/*0x43*/0x46,0xdc, // /*bls*/bne big_loop
0x46,0xdc, // bne big_loop
0x79,0x00,0x08,0xd6, // mov.w irHandleRxedByteIfAnyHasBeenRxed, r0
0x5e,0x00,0x69,0x3a, // jsr setProcToCallbyMainLoop
0x5a,0x00,0xba,0x62, // jmp common_epilogue
};
static const uint8_t sploit_trigger[] = { 0xf9,0x56 }; // write to f7e0
uint8_t flashrom_dump[0xc0000];
uint8_t flashrom_dump[0xc000];
int main(void) {
consoleDemoInit();
......@@ -88,7 +72,20 @@ int main(void) {
iprintf("sreg: %02x\n", vvv);
ir_init();
iprintf("ready! press A for comms test, X for EEPROM dump, Y for flash ROM dump!\n");
iprintf(
"ready! you can press:\n"
"- A for a connection test\n"
"- B to dump the walker's\n"
" internal FLASH ROM\n"
"- X to dump the walker's EEPROM\n"
" (user and game data)\n"
"- Y to restore the EEPROM\n"
" (UNTESTED! DATA LOSS HAZARD!)\n"
"- L to run code on the walker\n"
" (sd:/pwcode.bin)\n"
"- R to dump the IR cartridge\n"
" internal FLASH ROM\n"
);
pw_poll_tries = 0x10;
pw_poll_wait = pw_poll_wait_default;
......@@ -142,7 +139,7 @@ END:;
uint8_t mwahah[0x80];
if (pw_read_eeprom(sessid, i*sizeof mwahah, sizeof mwahah, mwahah)) {
iprintf("reading eeprom (%3d/512)\n", i);
iprintf("reading eeprom (%3d/512)\n", i+1);
} else {
iprintf("read failed :/\n");
break;
......@@ -161,6 +158,49 @@ END:;
}
if (run && (keys & KEY_Y) && !(oldkeys & KEY_Y)) {
if (pw_scan()) {
iprintf("ping!\n");
uint32_t sessid;
if (pw_do_synack(&sessid)) {
//iprintf("got sess! %08lx\n", sessid);
iprintf("WARN: doing untested stuff!\n");
// EEPROM dumper
FILE* fff = fopen("sd:/pweep.rom", "rb");
if (!fff) {
iprintf("can't open file :(\n");
goto LnopY;
}
for (size_t i = 0; i < 1024; ++i) {
uint8_t mwahah[0x40];
if (fread(mwahah, sizeof mwahah, 1, fff) != 1) {
iprintf("reading from SD file failed\n");
fclose(fff);
goto LnopY;
}
if (pw_write_eeprom(sessid, i*sizeof mwahah, sizeof mwahah, mwahah)) {
iprintf("writing eeprom (%4d/1024)\n", i+1);
} else {
iprintf("write failed :/\n");
break;
}
fwrite(mwahah, sizeof mwahah, 1, fff);
}
fclose(fff);
//fatUnmount("sd:");
LnopY:
if (pw_conn_end(sessid)) iprintf("closed correctly\n");
else iprintf("welp\n");
} else iprintf("can't connect\n");
}
else iprintf("no scan results\n");
}
if (run && (keys & KEY_B) && !(oldkeys & KEY_B)) {
if (pw_scan()) {
iprintf("ping!\n");
......@@ -204,6 +244,66 @@ END:;
else iprintf("no scan results\n");
}
if (run && (keys & KEY_R) && !(oldkeys & KEY_R)) {
FILE* fff = fopen("sd:/cartflash.rom", "wb");
if (!fff) {
iprintf("can't open file :(\n");
goto Lnop3;
}
for (size_t i = 0; i < (65536/256); ++i) {
uint8_t mwahah[0x100];
for (size_t j = 0; j < 256; ++j) {
mwahah[j] = ir_cmd4(j | (i << 8));
}
iprintf("reading cart flash (%3d/256)\n", i+1);
fwrite(mwahah, sizeof mwahah, 1, fff);
}
iprintf("done!\n");
fclose(fff);
Lnop3:;
}
if (run && (keys & KEY_L) && !(oldkeys & KEY_L)) {
if (pw_scan()) {
iprintf("ping!\n");
uint32_t sessid;
if (pw_do_synack(&sessid)) {
//iprintf("got sess! %08lx\n", sessid);
FILE* fff = fopen("sd:/pwcode.bin","rb");
if (!fff) {
iprintf("can't open file pwcode.bin\n");
goto LnopL;
}
uint8_t stuff[0x80];
size_t blobsize;
if ((blobsize = fread(stuff, 1, sizeof stuff, fff)) <= 0) {
iprintf("can't read file pwcode.bin\n");
close(fff);
goto LnopL;
}
close(fff);
if (!pw_write_mem(sessid, 0xf956, blobsize, stuff)) {
iprintf("can't install code\n");
goto LnopL;
}
if (!pw_write_mem(sessid, 0xf7e0, sizeof sploit_trigger,
sploit_trigger)) {
iprintf("can't install trigger\n");
goto LnopL;
}
LnopL:;
if (pw_conn_end(sessid)) iprintf("closed correctly\n");
else iprintf("welp\n");
} else iprintf("can't connect\n");
}
else iprintf("no scan results\n");
}
if (keys & KEY_START) break;
swiWaitForVBlank();
}
......
/*
* Copyright (c) 2020 PoroCYon <porocyon@titandemo.org>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <nds.h>
#include <stdio.h>
#include <stdint.h>
......@@ -261,7 +245,7 @@ bool pw_read_eeprom(uint32_t sessid, uint16_t addr, size_t size, uint8_t* dest)
pl[1] = addr&0xff;
pl[2] = size;
pw_send(pw_cmd_eepread_req, pw_extra_g2w, sessid, 3, pl);
pw_send(pw_cmd_eepread_req, addr >> 8, sessid, 3, pl);
if (pw_recv(pw_cmd_eepread_res, sessid, true) != 8+size || rxbuf[1] != pw_extra_w2g)
return false;
......@@ -271,6 +255,21 @@ bool pw_read_eeprom(uint32_t sessid, uint16_t addr, size_t size, uint8_t* dest)
return true;
}
bool pw_write_eeprom(uint32_t sessid, uint16_t addr, size_t size, const uint8_t* src) {
if (size > 255 || !src || size >= 0x80) return false;
uint8_t pl[0x80];
pl[0] = addr&0xff;
memcpy(&pl[1], src, size);
pw_send(pw_cmd_eepwrite_req, (uint8_t)(addr >> 8), sessid, size+1, src);
if (pw_recv(pw_cmd_eepwrite_res, sessid, true) != 8 || rxbuf[1] != pw_extra_w2g)
return false;
return true;
}
char pw_charconv_w2a(uint16_t wch) {
if (wch == 0 || ~(uint16_t)wch == 0) return 0;
......
PYTHON3 ?= python3
CROSS_COMPILE ?= h8300-hitachi-elf-
OBJCOPY ?= objcopy
AS := $(CROSS_COMPILE)$(AS)
LD := $(CROSS_COMPILE)$(LD)
OBJCOPY := $(CROSS_COMPILE)$(OBJCOPY)
ASFLAGS := --h-tick-hex -mach=h8300h -I./inc/ $(ASFLAGS)
LDFLAGS := -m h8300helf -T payload.ld -static $(LDFLAGS)
LDFLAGS := -nostdlib --build-id=none --relax $(LDFLAGS)
default: all
INPUT_SOURCES := $(wildcard src/*.s)
OBJECT_FILES := $(patsubst src/%.s,obj/%.s.o,$(INPUT_SOURCES))
ELVES_OUT := $(patsubst src/%.s,bin/%.elf,$(INPUT_SOURCES))
BINARIES_OUT := $(patsubst src/%.s,bin/%.bin,$(INPUT_SOURCES))
HEADERS_OUT := $(patsubst src/%.s,bin/%.h,$(INPUT_SOURCES))
all: $(BINARIES_OUT) $(HEADERS_OUT)
%/:
@mkdir -vp "$@"
obj/%.s.o: src/%.s obj/
$(AS) $(ASFLAGS) -o "$@" "$<"
bin/%.elf: obj/%.s.o bin/
$(LD) --cref -Map="$@.map" $(LDFLAGS) -o "$@" "$<"
bin/%.bin: bin/%.elf
$(OBJCOPY) -O binary "$<" "$@"
bin/%.h: bin/%.bin
$(PYTHON3) -c 'import sys;import textwrap;print(textwrap.fill(",".join("0x%02x"%x for x in sys.stdin.buffer.read())))' < "$<" > "$@"
clean:
@$(RM) -v $(OBJECT_FILES) $(ELVES_OUT) $(BINARIES_OUT) $(HEADERS_OUT)
.PHONY: default all clean
.PRECIOUS: $(OBJECT_FILES) $(ELVES_OUT) bin/ obj/
This diff is collapsed.
This diff is collapsed.
/* vim: set ts=8: */
#ifndef _POKEWALKER_PWIO_DEFS_H_
#define _POKEWALKER_PWIO_DEFS_H_
/******* IO1 *****************************************************************/
/* ROM */
#define FLMCR1 0xf020
#define FLMCR2 0xf021
#define FLPWCR 0xf022
#define EBR1 0xf023
#define FENR 0xf02b
/* RTC */
#define RTCFLG 0xf067
#define RSECDR 0xf068
#define RMINDR 0xf069
#define RHRDR 0xf06a
#define RWKDR 0xf06b
#define RTCCR1 0xf06c
#define RTCCR2 0xf06d
#define RTCCSR 0xf06f
/* IIC2 */
#define ICCR1 0xf078
#define ICCR2 0xf079
#define ICMR 0xf07a
#define ICIER 0xf07b
#define ICSR 0xf07c
#define SAR 0xf07d
#define ICDRT 0xf07e
#define ICDRR 0xf07f
/* system */
#define PFCR 0xf085
/* IO ports */
#define PUCR8 0xf086
#define PUCR9 0xf087
#define PODR9 0xf08c
/* timer B1 */
#define TMB1 0xf0d0
#define TCB1 0xf0d1
#define TLB1 0xf0d1
/* comparator */
#define CMCR0 0xf0dc
#define CMCR1 0xf0dd
#define CMDR 0xf0de
/* SSU */
#define SSCRH 0xf0e0
#define SSCRL 0xf0e1
#define SSCR 0xf0e0
#define SSMR 0xf0e2
#define SSER 0xf0e3
#define SSSR 0xf0e4
#define SSRDR 0xf0e9
#define SSTDR 0xf0eb
/* timer W */
#define TMRW 0xf0f0
#define TCRW 0xf0f1
#define TIERW 0xf0f2
#define TSRW 0xf0f3
#define TIOR0 0xf0f4
#define TIOR1 0xf0f5
#define TCNT 0xf0f6
#define GRA 0xf0f8
#define GRB 0xf0fa
#define GRC 0xf0fc
#define GRD 0xf0fe
/******* IO2 *****************************************************************/
/* AEC */
#define ECPWCR 0xff8c
#define ECPWDR 0xff8e
#define SPCR 0xff91
#define AESGR 0xff92
#define ECCR 0xff94
#define ECCSR 0xff95
#define ECH 0xff96
#define ECL 0xff97
#define EC 0xff96
/* SCI3/IrDA */
#define SMR3 0xff98
#define TDR3 0xff9b
#define SSR3 0xff9c
#define RDR3 0xff9d
#define SEMR 0xffa6
#define IrCR 0xffa7
/* WDT */
#define TMWD 0xffb0
#define TCSRWD1 0xffb1
#define TCSRWD2 0xffb2
#define TCDW 0xffb3
/* A/D converter */
#define ADRR 0xffbc
#define AMR 0xffbe
#define ADSR 0xffbf
/* IO ports */
#define PMR1 0xffc0
#define PMR3 0xffc2
#define PMRB 0xffca
#define PDR1 0xffd4
#define PDR3 0xffd6
#define PDR8 0xffdb
#define PDR9 0xffdc
#define PDRB 0xffde
#define PUCR1 0xffe0
#define PUCR3 0xffe1
#define PCR1 0xffe4
#define PCR3 0xffe6
#define PCR8 0xffeb
#define PCR9 0xffec
/* system, interrupts */
#define SYSCR1 0xfff0
#define SYSCR2 0xfff1
#define SYSCR 0xfff0
#define IEGR 0xfff2
#define IENR1 0xfff3
#define IENR2 0xfff4
#define OSCCR 0xfff5
#define IRR1 0xfff6
#define IRR2 0xfff7
#define CKSTPR1 0xfffa
#define CKSTPR2 0xfffb
#define CKSTPR 0xfffa
#endif
/* vim: set ft=gas ts=8: */
.ifndef _POKEWALKER_PWIO_DEFS_H_
.set _POKEWALKER_PWIO_DEFS_H_, 0
/******* IO1 *****************************************************************/
/* ROM */
.set FLMCR1, 0xf020
.set FLMCR2, 0xf021
.set FLPWCR, 0xf022
.set EBR1, 0xf023
.set FENR, 0xf02b
/* RTC */
.set RTCFLG, 0xf067
.set RSECDR, 0xf068
.set RMINDR, 0xf069
.set RHRDR, 0xf06a
.set RWKDR, 0xf06b
.set RTCCR1, 0xf06c
.set RTCCR2, 0xf06d
.set RTCCSR, 0xf06f
/* IIC2 */
.set ICCR1, 0xf078
.set ICCR2, 0xf079
.set ICMR, 0xf07a
.set ICIER, 0xf07b
.set ICSR, 0xf07c
.set SAR, 0xf07d
.set ICDRT, 0xf07e
.set ICDRR, 0xf07f
/* system */
.set PFCR, 0xf085
/* IO ports */
.set PUCR8, 0xf086
.set PUCR9, 0xf087
.set PODR9, 0xf08c
/* timer B1 */
.set TMB1, 0xf0d0
.set TCB1, 0xf0d1
.set TLB1, 0xf0d1
/* comparator */
.set CMCR0, 0xf0dc
.set CMCR1, 0xf0dd
.set CMDR, 0xf0de
/* SSU */
.set SSCRH, 0xf0e0
.set SSCRL, 0xf0e1
.set SSCR, 0xf0e0
.set SSMR, 0xf0e2
.set SSER, 0xf0e3
.set SSSR, 0xf0e4
.set SSRDR, 0xf0e9
.set SSTDR, 0xf0eb
/* timer W */
.set TMRW, 0xf0f0
.set TCRW, 0xf0f1
.set TIERW, 0xf0f2
.set TSRW, 0xf0f3
.set TIOR0, 0xf0f4
.set TIOR1, 0xf0f5