#include "std.h"
#include "emul.h"
#include "vars.h"
#include "debug.h"
#include "dbgpaint.h"
#include "dbgtrace.h"
#include "dbgrwdlg.h"
#include "fdd.h"
#include "util.h"
/*
dialogs design
┌───────────────────────┐
│Read from TR-DOS file │
├───────────────────────┤
│drive: A │
│file: 12345678 C │
│start: E000 end: FFFF │
└───────────────────────┘
┌───────────────────────┐
│Read from TR-DOS sector│
├───────────────────────┤
│drive: A │
│trk (00-9F): 00 │
│sec (00-0F): 08 │
│start: E000 end: FFFF │
└───────────────────────┘
┌───────────────────────┐
│Read RAW sectors │
├───────────────────────┤
│drive: A │
│cyl (00-4F): 00 side: 0│
│sec (00-0F): 08 num: 01│
│start: E000 │
└───────────────────────┘
┌───────────────────────┐
│Read from host file │
├───────────────────────┤
│file: 12345678.bin │
│start: C000 end: FFFF │
└───────────────────────┘
*/
enum FILEDLG_MODE { FDM_LOAD = 0, FDM_SAVE, FDM_DISASM };
unsigned addr = 0, end = 0xFFFF;
static unsigned char *memdata;
static unsigned rw_drive, rw_trk, rw_tsec;
static char fname[20] = "", trdname[9] = "12345678", trdext[2] = "C";
const int FILEDLG_X = 6;
const int FILEDLG_Y = 10;
const int FILEDLG_DX = 25;
static void rw_err(const char *msg)
{
MessageBox(wnd, msg, "Error", MB_OK | MB_ICONERROR);
}
static char query_file_addr(FILEDLG_MODE mode)
{
filledframe(FILEDLG_X, FILEDLG_Y, FILEDLG_DX, 5);
char ln[64];
static const char *titles[] = { " Read from binary file ",
" Write to binary file ",
" Disasm to text file " };
tprint(FILEDLG_X, FILEDLG_Y, titles[mode], FRM_HEADER);
tprint(FILEDLG_X+1, FILEDLG_Y+2, "file:", FFRAME_INSIDE);
sprintf(ln, (mode != FDM_LOAD)? "start: %04X end: %04X" : "start: %04X", addr, end);
tprint(FILEDLG_X+1, FILEDLG_Y+3, ln, FFRAME_INSIDE);
strcpy(str, fname);
for (;;)
{
if (!inputhex(FILEDLG_X+7,FILEDLG_Y+2,16, false))
return 0;
if (mode != FDM_LOAD)
break;
if (GetFileAttributes(str) != INVALID_FILE_ATTRIBUTES)
break;
}
strcpy(fname, str);
sprintf(ln, "%-16s", fname);
fillattr(FILEDLG_X+7,FILEDLG_Y+2,16);
int a1 = input4(FILEDLG_X+8,FILEDLG_Y+3,addr);
if (a1 == -1)
return 0;
addr = unsigned(a1);
fillattr(FILEDLG_X+8,FILEDLG_Y+3,4);
if (mode == FDM_LOAD)
return 1;
for (;;)
{
int e1 = input4(FILEDLG_X+18,FILEDLG_Y+3,end);
if (e1 == -1)
return 0;
if (unsigned(e1) < addr)
continue;
end = unsigned(e1);
return 1;
}
}
static void write_mem()
{
Z80 &cpu = CpuMgr.Cpu();
u8 *ptr = memdata;
for(unsigned a1 = addr; a1 <= end; a1++)
*cpu.DirectMem(a1) = *ptr++;
}
static void read_mem()
{
Z80 &cpu = CpuMgr.Cpu();
unsigned char *ptr = memdata;
for (unsigned a1 = addr; a1 <= end; a1++)
*ptr++ = cpu.DirectRm(a1);
}
static char rw_select_drive()
{
tprint(FILEDLG_X+1, FILEDLG_Y+2, "drive:", FFRAME_INSIDE);
for (;;) {
*(unsigned*)str = 'A' + rw_drive;
if (!inputhex(FILEDLG_X+8, FILEDLG_Y+2, 1, true)) return 0;
fillattr(FILEDLG_X+8, FILEDLG_Y+2, 1);
unsigned disk = unsigned(*str - 'A');
if (disk > 3) continue;
if (!comp.fdd[disk].rawdata) continue;
rw_drive = disk; return 1;
}
}
static char rw_trdos_sectors(FILEDLG_MODE mode)
{
filledframe(FILEDLG_X, FILEDLG_Y, FILEDLG_DX, 7);
const char *title = (mode == FDM_LOAD)? " Read from TR-DOS sectors" :
" Write to TR-DOS sectors ";
tprint(FILEDLG_X, FILEDLG_Y, title, FRM_HEADER);
char ln[64]; int t;
sprintf(ln, "trk (00-9F): %02X", rw_trk);
tprint(FILEDLG_X+1, FILEDLG_Y+3, ln, FFRAME_INSIDE);
sprintf(ln, "sec (00-0F): %02X", rw_tsec);
tprint(FILEDLG_X+1, FILEDLG_Y+4, ln, FFRAME_INSIDE);
sprintf(ln, "start: %04X end: %04X", addr, end);
tprint(FILEDLG_X+1, FILEDLG_Y+5, ln, FFRAME_INSIDE);
if (!rw_select_drive()) return 0;
FDD *fdd = &comp.fdd[rw_drive];
// if (fdd->sides != 2) { rw_err("single-side TR-DOS disks are not supported"); return 0; }
t = input2(FILEDLG_X+14, FILEDLG_Y+3, rw_trk);
if (t == -1) return 0; else rw_trk = unsigned(t);
fillattr(FILEDLG_X+14, FILEDLG_Y+3, 2);
t = input2(FILEDLG_X+14, FILEDLG_Y+4, rw_tsec);
if (t == -1) return 0; else rw_tsec = unsigned(t);
fillattr(FILEDLG_X+14, FILEDLG_Y+4, 2);
t = input4(FILEDLG_X+8,FILEDLG_Y+5,addr);
if (t == -1) return 0; else addr = unsigned(t);
fillattr(FILEDLG_X+8,FILEDLG_Y+5,4);
for (;;) {
t = input4(FILEDLG_X+18,FILEDLG_Y+5,end);
fillattr(FILEDLG_X+18,FILEDLG_Y+5,4);
if (t == -1) return 0;
if (unsigned(t) < addr) continue;
end = unsigned(t); break;
}
unsigned offset = 0;
if (mode == FDM_SAVE) read_mem();
unsigned trk = rw_trk, sec = rw_tsec;
TRKCACHE tc; tc.clear();
for (;;) {
int left = int(end+1) - int(addr+offset);
if (left <= 0) break;
if (left > 0x100) left = 0x100;
tc.seek(fdd, trk/2, trk & 1, LOAD_SECTORS);
if (!tc.trkd) { sprintf(ln, "track #%02X not found", trk); rw_err(ln); break; }
const SECHDR *hdr = tc.get_sector(sec+1, 1);
if (!hdr || !hdr->data) { sprintf(ln, "track #%02X, sector #%02X not found", trk, sec); rw_err(ln); break; }
if (hdr->l != 1) { sprintf(ln, "track #%02X, sector #%02X is not 256 bytes", trk, sec); rw_err(ln); break; }
if (mode == FDM_LOAD) {
memcpy(memdata+offset, hdr->data, size_t(left));
} else {
tc.write_sector(sec+1, 1, memdata+offset);
fdd->optype |= 1;
}
offset += unsigned(left);
if(++sec == 0x10)
{
trk++;
sec = 0;
}
}
end = addr + offset - 1;
if (mode == FDM_LOAD) write_mem();
return 1;
}
static char wr_trdos_file()
{
filledframe(FILEDLG_X, FILEDLG_Y, FILEDLG_DX, 6);
const char *title = " Write to TR-DOS file ";
tprint(FILEDLG_X, FILEDLG_Y, title, FRM_HEADER);
char ln[64]; int t;
sprintf(ln, "file: %-8s %s", trdname, trdext);
tprint(FILEDLG_X+1, FILEDLG_Y+3, ln, FFRAME_INSIDE);
sprintf(ln, "start: %04X end: %04X", addr, end);
tprint(FILEDLG_X+1, FILEDLG_Y+4, ln, FFRAME_INSIDE);
if (!rw_select_drive()) return 0;
FDD *fdd = &comp.fdd[rw_drive];
// if (fdd->sides != 2) { rw_err("single-side TR-DOS disks are not supported"); return 0; }
strcpy(str, trdname);
if (!inputhex(FILEDLG_X+8,FILEDLG_Y+3,8,false)) return 0;
fillattr(FILEDLG_X+8,FILEDLG_Y+3,8);
strcpy(trdname, str);
for (size_t ptr = strlen(trdname); ptr < 8; trdname[ptr++] = ' ');
trdname[8] = 0;
strcpy(str, trdext);
if (!inputhex(FILEDLG_X+17,FILEDLG_Y+3,1,false)) return 0;
fillattr(FILEDLG_X+17,FILEDLG_Y+3,1);
trdext[0] = str[0]; trdext[1] = 0;
t = input4(FILEDLG_X+8,FILEDLG_Y+4,addr);
if (t == -1) return 0; else addr = unsigned(t);
fillattr(FILEDLG_X+8,FILEDLG_Y+4,4);
for (;;) {
t = input4(FILEDLG_X+18,FILEDLG_Y+4,end);
fillattr(FILEDLG_X+18,FILEDLG_Y+4,4);
if (t == -1) return 0;
if (unsigned(t) < addr) continue;
end = unsigned(t); break;
}
read_mem();
unsigned char hdr[16];
memcpy(hdr, trdname, 8);
hdr[8] = u8(*trdext);
unsigned sz = end-addr+1;
*(unsigned short*)(hdr+9) = u16(addr);
*(unsigned short*)(hdr+11) = u16(sz);
hdr[13] = u8(align_by(sz, 0x100U) / 0x100); // sector size
fdd->optype |= 1;
if (!fdd->addfile(hdr, memdata)) { rw_err("write error"); return 0; }
return 1;
}
void mon_load()
{
static MENUITEM items[] =
{ { "from binary file", MENUITEM::LEFT },
{ "from TR-DOS file", MENUITEM::LEFT },
{ "from TR-DOS sectors", MENUITEM::LEFT },
{ "from raw sectors of FDD image", MENUITEM::LEFT } };
static MENUDEF menu = { items, 3, "Load data to memory...", 0 };
if(!handle_menu(&menu))
return;
unsigned char bf[0x10000];
memdata = bf;
switch (menu.pos)
{
case 0:
{
if (!query_file_addr(FDM_LOAD))
return;
FILE *ff = fopen(fname, "rb");
if (!ff)
return;
size_t sz = fread(bf, 1, sizeof(bf), ff);
fclose(ff);
end = unsigned(addr + sz - 1);
end = min(end, 0xFFFFU);
write_mem();
return;
}
case 1:
{
rw_err("file selector\r\nis not implemented");
return;
}
case 2:
{
rw_trdos_sectors(FDM_LOAD);
return;
}
case 3:
{
return;
}
}
}
void mon_save()
{
static MENUITEM items[] =
{ { "to binary file", MENUITEM::LEFT },
{ "to TR-DOS file", MENUITEM::LEFT },
{ "to TR-DOS sectors", MENUITEM::LEFT },
{ "as Z80 disassembly", MENUITEM::LEFT },
{ "to raw sectors of FDD image", (MENUITEM::FLAGS)(MENUITEM::LEFT | MENUITEM::DISABLED) } };
static MENUDEF menu = { items, 4, "Save data from memory...", 0 };
if (!handle_menu(&menu)) return;
unsigned char bf[0x10000]; memdata = bf;
switch (menu.pos)
{
case 0:
{
if (!query_file_addr(FDM_SAVE)) return;
read_mem();
FILE *ff = fopen(fname, "wb");
if (!ff) return;
fwrite(bf, 1, end+1-addr, ff);
fclose(ff);
return;
}
case 1:
{
wr_trdos_file();
return;
}
case 2:
{
rw_trdos_sectors(FDM_SAVE);
return;
}
case 3:
{
if (!query_file_addr(FDM_DISASM)) return;
FILE *ff = fopen(fname, "wt");
if (!ff) return;
for (unsigned a = addr; a <= end; ) {
// char line[64]; //Alone Coder 0.36.7
char line[16+129]; //Alone Coder 0.36.7
a += unsigned(disasm_line(a, line));
fprintf(ff, "%s\n", line);
}
fclose(ff);
return;
}
case 4:
{
return;
}
}
}