From e3b4666c2d405e48bcadb6789032060f51fbf349 Mon Sep 17 00:00:00 2001 From: Hiroshi OGINO Date: Sun, 6 Aug 2023 11:42:51 +0900 Subject: [PATCH 1/9] =?UTF-8?q?PC-8001mkII=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gdemu/SConstruct | 29 ++++++++++++++++++++++++++++- gdemu/src/gdemu.cpp | 5 +++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/gdemu/SConstruct b/gdemu/SConstruct index 1e89c22..353bd17 100644 --- a/gdemu/SConstruct +++ b/gdemu/SConstruct @@ -4,7 +4,7 @@ import sys opts = Variables([], ARGUMENTS) -emu_array = ["", "x1", "x1t", "msx", "pc88ma"] +emu_array = ["", "x1", "x1t", "msx", "pc88ma", "pc80mk2"] opts.Add(EnumVariable("emu", "Target emulator", "", emu_array)) @@ -31,6 +31,8 @@ if lenv["emu"] == "msx": env.Append(CPPDEFINES=['_MSX1']) elif lenv["emu"] == "pc88ma": env.Append(CPPDEFINES=['_PC8801MA']) +elif lenv["emu"] == "pc80mk2": + env.Append(CPPDEFINES=['_PC8001MK2']) elif lenv["emu"] == "x1t": env.Append(CPPDEFINES=['_X1','_X1TURBO']) else: @@ -101,6 +103,31 @@ elif lenv["emu"] == "pc88ma": sources.append("src/emulator/vm/pc8801/pc88.cpp") sources.append("src/emulator/vm/pc8801/pc8801.cpp") sources.append("src/emulator/vm/pc8801/diskio.cpp") +elif lenv["emu"] == "pc80mk2": + sources.append("src/emulator/vm/disk.cpp") + sources.append("src/emulator/vm/harddisk.cpp") + sources.append("src/emulator/vm/event.cpp") + sources.append("src/emulator/vm/prnfile.cpp") + sources.append("src/emulator/vm/i8251.cpp") + sources.append("src/emulator/vm/i8255.cpp") + sources.append("src/emulator/vm/upd1990a.cpp") + sources.append("src/emulator/vm/ym2203.cpp") + sources.append("src/emulator/vm/z80.cpp") + sources.append("src/emulator/vm/noise.cpp") + sources.append("src/emulator/vm/pc80s31k.cpp") + sources.append("src/emulator/vm/upd765a.cpp") + sources.append("src/emulator/vm/scsi_dev.cpp") + sources.append("src/emulator/vm/scsi_hdd.cpp") + sources.append("src/emulator/vm/scsi_host.cpp") + sources.append("src/emulator/vm/scsi_cdrom.cpp") + sources.append("src/emulator/vm/ym2151.cpp") + sources.append("src/emulator/vm/ay_3_891x.cpp") + sources.append("src/emulator/vm/i8253.cpp") + sources.append("src/emulator/vm/pcm1bit.cpp") + sources.append("src/emulator/vm/pcm8bit.cpp") + sources.append("src/emulator/vm/pc8801/pc88.cpp") + sources.append("src/emulator/vm/pc8801/pc8801.cpp") + sources.append("src/emulator/vm/pc8801/diskio.cpp") else: sources.append("src/emulator/vm/ay_3_891x.cpp") sources.append("src/emulator/vm/event.cpp") diff --git a/gdemu/src/gdemu.cpp b/gdemu/src/gdemu.cpp index 3f3a025..5dcda0a 100644 --- a/gdemu/src/gdemu.cpp +++ b/gdemu/src/gdemu.cpp @@ -147,6 +147,11 @@ void GDEmu::init() { file_copy("res://N80.ROM", "user://N80.ROM"); #endif +#if defined(_PC8001MK2) + file_copy("res://N80_2.ROM", "user://N80_2.ROM"); + file_copy("res://KANJI1.ROM", "user://KANJI1.ROM"); +#endif + // フロッピーアクセス音 file_copy("res://FDDSEEK.BIN", "user://FDDSEEK.WAV"); From 08cd1fbea6cb5743990f81000aa97fa4a4b49aee Mon Sep 17 00:00:00 2001 From: Hiroshi OGINO Date: Sun, 6 Aug 2023 16:13:28 +0900 Subject: [PATCH 2/9] =?UTF-8?q?PC-8001mk2=5FSD=E3=81=AB=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * まだ全体的に怪しいです(現状はWindowsのみで確認) --- gdemu/SConstruct | 1 + gdemu/src/emulator/vm/pc80sd.cpp | 1407 +++++++++++++++++++++++ gdemu/src/emulator/vm/pc80sd.h | 136 +++ gdemu/src/emulator/vm/pc8801/pc88.cpp | 53 +- gdemu/src/emulator/vm/pc8801/pc88.h | 18 + gdemu/src/emulator/vm/pc8801/pc8801.cpp | 23 + gdemu/src/emulator/vm/pc8801/pc8801.h | 10 + gdemu/src/gdemu.cpp | 36 + 8 files changed, 1683 insertions(+), 1 deletion(-) create mode 100644 gdemu/src/emulator/vm/pc80sd.cpp create mode 100644 gdemu/src/emulator/vm/pc80sd.h diff --git a/gdemu/SConstruct b/gdemu/SConstruct index 353bd17..12fd3bb 100644 --- a/gdemu/SConstruct +++ b/gdemu/SConstruct @@ -128,6 +128,7 @@ elif lenv["emu"] == "pc80mk2": sources.append("src/emulator/vm/pc8801/pc88.cpp") sources.append("src/emulator/vm/pc8801/pc8801.cpp") sources.append("src/emulator/vm/pc8801/diskio.cpp") + sources.append("src/emulator/vm/pc80sd.cpp") else: sources.append("src/emulator/vm/ay_3_891x.cpp") sources.append("src/emulator/vm/event.cpp") diff --git a/gdemu/src/emulator/vm/pc80sd.cpp b/gdemu/src/emulator/vm/pc80sd.cpp new file mode 100644 index 0000000..6c7c8bf --- /dev/null +++ b/gdemu/src/emulator/vm/pc80sd.cpp @@ -0,0 +1,1407 @@ +/* + Skelton for retropc emulator + + Date : 2023.07.30- + + [ PC-8001(mk2)_SD ] +*/ + +#include "pc80sd.h" +#include "../fileio.h" + +#define EVENT_TIMER 1 + +#define SIG_I8255_PORT_A 0 +#define SIG_I8255_PORT_B 1 +#define SIG_I8255_PORT_C 2 + +PC80SD *current_pc80sd; + +#if defined(_WIN32) || defined(_WIN64) +CRITICAL_SECTION signal_cs; +#else +pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; +#endif + +// ۑtH_ +const _TCHAR *sd_folder_name = _T("SD"); + +unsigned long r_count = 0; +unsigned long f_length = 0; +char m_name[40]; +char f_name[40]; +char c_name[40]; +char new_name[40]; +char w_name[40]; +bool eflg = false; +unsigned int s_adrs, e_adrs, w_length, w_len1, w_len2, s_adrs1, s_adrs2, b_length; + +FILEIO *file, *w_file; + +class SDFileEntry +{ +private: + bool _isValid; + char name[1024]; + +public: + SDFileEntry() + { + invalidate(); + } + void invalidate() + { + _isValid = false; + } + SDFileEntry(const char *name) + { + strncpy(this->name, name, strlen(name) + 1); + _isValid = true; + } + + bool getName(char *name, int len) + { + if (!_isValid) + { + return false; + } + strncpy(name, this->name, len); + return true; + } + + bool isValid() { return _isValid; } +}; + +class SDFile +{ +private: + char base_path[1024]; + +#if defined(_WIN32) || defined(_WIN64) + WIN32_FIND_DATA ffd; + char szDir[MAX_PATH]; + HANDLE hFind = INVALID_HANDLE_VALUE; +#else + DIR *dir; + struct dirent *dp; +#endif + SDFileEntry currentEntry; + +public: + SDFile() + { + memset(base_path, 0, sizeof(base_path)); + } + bool open(const char *path); + SDFileEntry openNextFile(); + void rewindDirectory(); + void close(); + static bool exists(const char *path); + static bool remove(const char *path); +}; + +const _TCHAR *create_sd_path(const char *path) +{ + static _TCHAR file_path[8][_MAX_PATH]; + static unsigned int table_index = 0; + unsigned int output_index = (table_index++) & 7; + + const _TCHAR *dir_path = create_local_path(sd_folder_name); + + // Ldir_pathpathAătpX +#if defined(_WIN32) || defined(_WIN64) + _stprintf(file_path[output_index], _T("%s\\%s"), dir_path, path); +#else + _stprintf(file_path[output_index], _T("%s/%s"), dir_path, path); +#endif + + return (const _TCHAR *)file_path[output_index]; +} + +bool SDFile::exists(const char *path) +{ + FILE *file = fopen(create_sd_path(path), "r"); + if (file != NULL) + { + fclose(file); + return true; + } + + return false; +} + +bool SDFile::remove(const char *path) +{ + return ::remove(create_sd_path(path)); +} + +void SDFile::rewindDirectory() +{ + close(); + open(base_path); +} + +SDFileEntry SDFile::openNextFile() +{ + SDFileEntry result; + if (currentEntry.isValid()) + { + result = currentEntry; + } +#if defined(_WIN32) || defined(_WIN64) + bool updated = false; + while (FindNextFile(hFind, &ffd) != 0) + { + TCHAR *wpFileName = ffd.cFileName; + /* + L"."L".."̓XLbv + */ + if (L'.' == wpFileName[0]) + { + if ((L'\0' == wpFileName[1]) || (L'.' == wpFileName[1] && L'\0' == wpFileName[2])) + { + continue; + } + } + // tH_̓XLbv + if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + continue; + } + + currentEntry = SDFileEntry(ffd.cFileName); + updated = true; + break; + } + + // currentEntryXVoȂꍇAŏIƂȂ + if (!updated) + { + SDFileEntry invalidEntry; + currentEntry = invalidEntry; + } + +#else + bool updated = false; + while((ent = readdir(dir)) != NULL) + { + struct stat st; + while ((ent = readdir(dir)) != NULL) + { + stat(ent->d_name, &st); + if (S_ISDIR(st.st_mode)) { + continue; + } else if(S_ISREG(st.st_mode)) { + // t@C擾 + currentEntry = SDFileEntry(ent->d_name); + updated = true; + break; + } + } + } + + // currentEntryXVoȂꍇAŏIƂȂ + if (!updated) + { + SDFileEntry invalidEntry; + currentEntry = invalidEntry; + closedir(dir); + } +#endif + return result; +} + +bool SDFile::open(const char *path) +{ + strcpy(base_path, path); +#if defined(_WIN32) || defined(_WIN64) + strncpy(szDir, path, strlen(path) + 1); + strncat(szDir, "\\*", 3); + + hFind = FindFirstFile(szDir, &ffd); + if (INVALID_HANDLE_VALUE == hFind) + { + return false; + } + + do + { + TCHAR *wpFileName = ffd.cFileName; + /* + L"."L".."̓XLbv + */ + if (L'.' == wpFileName[0]) + { + if ((L'\0' == wpFileName[1]) || (L'.' == wpFileName[1] && L'\0' == wpFileName[2])) + { + continue; + } + } + // –ڂEntryĂ + currentEntry = SDFileEntry(ffd.cFileName); + break; + } while (FindNextFile(hFind, &ffd) != 0); +#else + if ((dir = opendir(path)) != NULL) + { + struct stat st; + while ((ent = readdir(dir)) != NULL) + { + stat(ent->d_name, &st); + if (S_ISDIR(st.st_mode)) { + continue; + } else if(S_ISREG(st.st_mode)) { + // t@C擾 + currentEntry = SDFileEntry(ent->d_name); + break; + } + } + } +#endif + return true; +} + +void SDFile::close() +{ +#if defined(_WIN32) || defined(_WIN64) + FindClose(hFind); +#else +#endif +} + +// ->啶 +char upper(char c) +{ + if ('a' <= c && c <= 'z') + { + c = c - ('a' - 'A'); + } + return c; +} + +// f_namec_namec_name0x00o܂Ŕr +// FILENAME COMPARE +bool f_match(char *f_name, char *c_name) +{ + bool flg1 = true; + unsigned int lp1 = 0; + while (lp1 <= 32 && c_name[0] != 0x00 && flg1 == true) + { + if (upper(f_name[lp1]) != c_name[lp1]) + { + flg1 = false; + } + lp1++; + if (c_name[lp1] == 0x00) + { + break; + } + } + return flg1; +} + +void thread_join(volatile PC80SD *p) +{ +#if defined(_WIN32) || defined(_WIN64) + WaitForSingleObject((HANDLE)p->threadHandle, INFINITE); + CloseHandle((HANDLE)p->threadHandle); +#else + pthread_join(threadID, NULL); +#endif +} + +void thread_yield() +{ + // Yield to other threads +#if defined(_WIN32) || defined(_WIN64) + SwitchToThread(); +#else + sched_yield(); +#endif +} + +void thread_sleep(int timer_count) +{ + current_pc80sd->write_signals_thread(-1, timer_count); + while(current_pc80sd->sleep_counter > 0) + { + thread_yield(); + } + +//#if defined(_WIN32) || defined(_WIN64) +// // Windows̏ꍇ +// Sleep(milliseconds); // ̓~b +//#else +// // Linux/Mac̏ꍇ +// usleep(microseconds); // ̓}CNb +//#endif +} + +uint8_t rcv4bit() +{ + // HIGHɂȂ܂Ń[v + while ((current_pc80sd->port[2].reg & 0x4) == 0 && !current_pc80sd->request_terminate) + { + thread_yield(); + } + if (current_pc80sd->request_terminate) + { + return 0; + } + + // M + uint8_t j_data = current_pc80sd->port[0].reg & 0xf; + + // FLGZbg + current_pc80sd->write_signals_thread(2, 0x80); + + // LOWɂȂ܂Ń[v + while ((current_pc80sd->port[2].reg & 0x4) != 0 && !current_pc80sd->request_terminate) + { + thread_yield(); + } + if (current_pc80sd->request_terminate) + { + return 0; + } + + // FLGZbg + current_pc80sd->write_signals_thread(2, 0x00); + + // rcv1byteꍇLOW̃`FbNZ80łȂ̂ + thread_sleep(100); + + return (j_data); +} + +// 1BYTEM +void snd1byte(byte i_data) +{ + if (current_pc80sd->request_terminate) + { + return; + } + // ʃrbg8rbgZbg + current_pc80sd->write_signals_thread(1, i_data); + // FLGPINHIGH + current_pc80sd->write_signals_thread(2, 0x80); + + // HIGHɂȂ܂Ń[v + while ((current_pc80sd->port[2].reg & 0x4) == 0 && !current_pc80sd->request_terminate) + { + thread_yield(); + } + if (current_pc80sd->request_terminate) + { + return; + } + + current_pc80sd->write_signals_thread(2, 0x00); + + // LOWɂȂ܂Ń[v + while ((current_pc80sd->port[2].reg & 0x4) != 0 && !current_pc80sd->request_terminate) + { + thread_yield(); + } + if (current_pc80sd->request_terminate) + { + return; + } +} + +uint8_t rcv1byte() +{ + uint8_t i_data = 0; + i_data = rcv4bit() * 16; + i_data = i_data + rcv4bit(); + return i_data; +} + +// SD-CARDFILELIST +void dirlist() +{ + // r擾 32+1܂ + for (unsigned int lp1 = 0; lp1 <= 32; lp1++) + { + c_name[lp1] = rcv1byte(); + } + + SDFile file; + bool result = file.open(create_local_path(sd_folder_name)); + if (result) + { + // ԃR[hM(OK) + snd1byte(0x00); + + SDFileEntry entry = file.openNextFile(); + int cntl2 = 0; + unsigned int br_chk = 0; + int page = 1; + // So͂̏ꍇɂ16o͂Ƃňꎞ~AL[͂ɂpAł؂I + while (br_chk == 0) + { + if (entry.isValid()) + { + entry.getName(f_name, 36); + unsigned int lp1 = 0; + // ꌏM + // rŃt@Cl[/re擪10܂ŔrĈv̂o + if (f_match(f_name, c_name)) + { + while (lp1 <= 36 && f_name[lp1] != 0x00) + { + snd1byte(upper(f_name[lp1])); + lp1++; + } + snd1byte(0x0D); + snd1byte(0x00); + cntl2++; + } + } + if (!entry.isValid() || cntl2 > 15) + { + // pEł؂Iwv + snd1byte(0xfe); + + // IwM(0:p B:Oy[W ȊO:ł؂) + br_chk = rcv1byte(); + // Oy[W + if (br_chk == 0x42) + { + // 擪t@C + file.rewindDirectory(); + // entrylXV + entry = file.openNextFile(); + // x擪t@C + file.rewindDirectory(); + if (page <= 2) + { + // ݃y[W1y[W2y[WȂ1y[Wڂɖ߂鏈 + page = 0; + } + else + { + // ݃y[W3y[Wȍ~ȂOXy[W܂ł̃t@Cǂݔ΂ + page = page - 2; + cntl2 = 0; + while (cntl2 < page * 16) + { + entry = file.openNextFile(); + if (f_match(f_name, c_name)) + { + cntl2++; + } + } + } + br_chk = 0; + } + page++; + cntl2 = 0; + } + // t@C܂Ȃ玟ǂݍ݁AȂΑł؂w + if (entry.isValid()) + { + entry = file.openNextFile(); + } + else + { + br_chk = 1; + } + // FDĽʂ18Ȃpwvɂ̂܂܏I + if (!entry.isValid() && cntl2 < 16 && page == 1) + { + break; + } + } + // Iw + snd1byte(0xFF); + snd1byte(0x00); + } + else + { + snd1byte(0xf1); + } +} + +void addcmt(char *f_name, char *m_name) +{ + unsigned int lp1 = 0; + while (f_name[lp1] != 0x00) + { + m_name[lp1] = f_name[lp1]; + lp1++; + } + if (f_name[lp1 - 4] != '.' || + (f_name[lp1 - 3] != 'C' && + f_name[lp1 - 3] != 'c') || + (f_name[lp1 - 2] != 'M' && + f_name[lp1 - 2] != 'm') || + (f_name[lp1 - 1] != 'T' && + f_name[lp1 - 1] != 't')) + { + m_name[lp1++] = '.'; + m_name[lp1++] = 'c'; + m_name[lp1++] = 'm'; + m_name[lp1++] = 't'; + } + m_name[lp1] = 0x00; +} + +// r擾 32+1܂Ŏ擾A_uR[e[V͖ +void receive_name(char *f_name) +{ + char r_data; + unsigned int lp2 = 0; + for (unsigned int lp1 = 0; lp1 <= 32; lp1++) + { + r_data = rcv1byte(); + if (r_data != 0x22) + { + f_name[lp2] = r_data; + lp2++; + } + } +} + +// MONITOR LR}h .CMT LOAD +void cmt_load() +{ + boolean flg = false; + // DOSt@C擾 + receive_name(m_name); + // t@C̎w肪邩 + if (m_name[0] != 0x00) + { + addcmt(m_name, f_name); + + // w肪ꍇ + // t@C݂ȂERROR + if (SDFile::exists(f_name) == true) + { + // t@CI[v + file = new FILEIO(); + if (file->Fopen(create_local_path("%s/%s", sd_folder_name, f_name), FILEIO_READ_BINARY)) + { + // f_lengthݒAr_count + f_length = file->FileLength(); + r_count = 0; + // ԃR[hM(OK) + snd1byte(0x00); + flg = true; + } + else + { + snd1byte(0xf0); + flg = false; + } + } + else + { + snd1byte(0xf1); + flg = false; + } + } + else + { + // t@C̎w肪Ȃꍇ + // t@CGhɂȂĂȂ + if (f_length > r_count) + { + snd1byte(0x00); + flg = true; + } + else + { + snd1byte(0xf1); + flg = false; + } + } + + // ǂ΃t@CGh܂œǂݍ݂𑱍s + if (flg == true) + { + int rdata = 0; + + // wb_[oĂ܂œǂݔ΂ + while (rdata != 0x3a && rdata != 0xd3) + { + rdata = file->FgetUint8(); + r_count++; + } + // wb_[M + snd1byte(rdata); + + // wb_[0x3aȂ瑱sAႦ΃G[ + if (rdata == 0x3a) + { + // START ADDRESS HI𑗐M + s_adrs1 = file->FgetUint8(); + r_count++; + snd1byte(s_adrs1); + + // START ADDRESS LO𑗐M + s_adrs2 = file->FgetUint8(); + r_count++; + snd1byte(s_adrs2); + s_adrs = s_adrs1 * 256 + s_adrs2; + + // CHECK SUM𑗐M + rdata = file->FgetUint8(); + r_count++; + snd1byte(rdata); + + // HEADER𑗐M + rdata = file->FgetUint8(); + r_count++; + snd1byte(rdata); + + // f[^𑗐M + b_length = file->FgetUint8(); + r_count++; + snd1byte(b_length); + + // f[^0x00łȂԃ[v + while (b_length != 0x00) + { + for (unsigned int lp1 = 0; lp1 <= b_length; lp1++) + { + // f[^ǂݍőM + rdata = file->FgetUint8(); + r_count++; + snd1byte(rdata); + } + // CHECK SUM𑗐M + rdata = file->FgetUint8(); + r_count++; + snd1byte(rdata); + // f[^𑗐M + b_length = file->FgetUint8(); + r_count++; + snd1byte(b_length); + } + // f[^0x00̌㏈ + // CHECK SUM𑗐M + rdata = file->FgetUint8(); + r_count++; + snd1byte(rdata); + + // t@CGhɒBĂFILE CLOSE + if (f_length == r_count) + { + file->Fclose(); + delete file; + file = nullptr; + } + } + else + { + file->Fclose(); + delete file; + file = nullptr; + } + } +} + +// 5F9EH CMT 1Byteǂݍݏ̑ցAOPENĂt@C̑1Byteǂݍ݁AM +void cmt_5f9e(void) +{ + if (file == nullptr) + { + // JĂȂ + return; + } + int rdata = file->FgetUint8(); + r_count++; + snd1byte(rdata); + // t@CGh܂ŒBĂFILE CLOSE + if (f_length == r_count) + { + file->Fclose(); + delete file; + file = nullptr; + } +} + +void w_body(void) +{ + byte r_data, csum; + // wb_[ 0x3A + w_file->FputUint8(char(0x3A)); + // X^[gAhX擾A + s_adrs1 = rcv1byte(); + s_adrs2 = rcv1byte(); + w_file->FputUint8(s_adrs2); + w_file->FputUint8(s_adrs1); + // CHECK SUMvZA + csum = 0 - (s_adrs1 + s_adrs2); + w_file->FputUint8(csum); + // X^[gAhXZo + s_adrs = s_adrs1 + s_adrs2 * 256; + // GhAhX擾 + s_adrs1 = rcv1byte(); + s_adrs2 = rcv1byte(); + // GhAhXZo + e_adrs = s_adrs1 + s_adrs2 * 256; + // t@CZoAubNZo + w_length = e_adrs - s_adrs + 1; + w_len1 = w_length / 255; + w_len2 = w_length % 255; + + // f[^MA + // 0xFFubN + while (w_len1 > 0) + { + w_file->FputUint8(char(0x3A)); + w_file->FputUint8(char(0xFF)); + csum = 0xff; + for (unsigned int lp1 = 1; lp1 <= 255; lp1++) + { + r_data = rcv1byte(); + w_file->FputUint8(r_data); + csum = csum + r_data; + } + // CHECK SUMvZA + csum = 0 - csum; + w_file->FputUint8(csum); + w_len1--; + } + + // [ubN + if (w_len2 > 0) + { + w_file->FputUint8(char(0x3A)); + w_file->FputUint8(w_len2); + csum = w_len2; + for (unsigned int lp1 = 1; lp1 <= w_len2; lp1++) + { + r_data = rcv1byte(); + w_file->FputUint8(r_data); + csum = csum + r_data; + } + // CHECK SUMvZA + csum = 0 - csum; + w_file->FputUint8(csum); + } + w_file->FputUint8(char(0x3A)); + w_file->FputUint8(char(0x00)); + w_file->FputUint8(char(0x00)); +} + +// MONITOR WR}h .CMT SAVE +void cmt_save(void) +{ + byte r_data, csum; + // DOSt@C擾 + receive_name(m_name); + // t@C̎w肪΃G[ + if (m_name[0] != 0x00) + { + addcmt(m_name, f_name); + + if (w_file != nullptr) + { + w_file->Fclose(); + } + // t@C݂delete + if (SDFile::exists(f_name) == true) + { + SDFile::remove(f_name); + } + // t@CI[v + w_file = new FILEIO(); + // SD.open( f_name, FILE_WRITE ); + if (w_file->Fopen(create_sd_path(f_name), FILEIO_WRITE_BINARY)) + { + // ԃR[hM(OK) + snd1byte(0x00); + w_body(); + w_file->Fclose(); + delete w_file; + w_file = nullptr; + } + else + { + snd1byte(0xf0); + } + } + else + { + snd1byte(0xf6); + } +} + +// BASICvOSAVE +void bas_save(void) +{ + unsigned int lp1; + + // DOSt@C擾 + receive_name(m_name); + // t@C̎w肪΃G[ + if (m_name[0] != 0x00) + { + addcmt(m_name, f_name); + + if (w_file) + { + w_file->Fclose(); + } + // t@C݂delete + if (SDFile::exists(f_name) == true) + { + SDFile::remove(f_name); + } + // t@CI[v + // w_file = SD.open( f_name, FILE_WRITE ); + w_file = new FILEIO(); + if (w_file->Fopen(create_sd_path(f_name), FILEIO_WRITE_BINARY)) + { + // ԃR[hM(OK) + snd1byte(0x00); + + // X^[gAhX擾 + s_adrs1 = rcv1byte(); + s_adrs2 = rcv1byte(); + // X^[gAhXZo + s_adrs = s_adrs1 + s_adrs2 * 256; + // GhAhX擾 + s_adrs1 = rcv1byte(); + s_adrs2 = rcv1byte(); + // GhAhXZo + e_adrs = s_adrs1 + s_adrs2 * 256; + // wb_[ 0xD3 x 9񏑂 + for (lp1 = 0; lp1 <= 9; lp1++) + { + w_file->FputUint8(char(0xD3)); + } + // DOSt@C̐擪6t@Cl[Ƃď + for (lp1 = 0; lp1 <= 5; lp1++) + { + w_file->FputUint8(m_name[lp1]); + } + // f[^ (e_adrs - s_adrs +1)MA + for (lp1 = s_adrs; lp1 <= e_adrs; lp1++) + { + w_file->FputUint8(rcv1byte()); + } + // I 0x00 x 9񏑂 + for (lp1 = 1; lp1 <= 9; lp1++) + { + w_file->FputUint8(char(0x00)); + } + w_file->Fclose(); + delete w_file; + w_file = nullptr; + } + else + { + snd1byte(0xf0); + } + } + else + { + snd1byte(0xf1); + } +} + +// BASICvOKILL +void bas_kill(void) +{ + unsigned int lp1; + + // DOSt@C擾 + receive_name(m_name); + // t@C̎w肪΃G[ + if (m_name[0] != 0x00) + { + addcmt(m_name, f_name); + + // ԃR[hM(OK) + snd1byte(0x00); + // t@C݂delete + if (SDFile::exists(f_name) == true) + { + SDFile::remove(f_name); + // ԃR[hM(OK) + snd1byte(0x00); + } + else + { + snd1byte(0xf1); + } + } + else + { + snd1byte(0xf1); + } +} + +// BASICvOLOAD +void bas_load(void) +{ + bool flg = false; + // DOSt@C擾 + receive_name(m_name); + // t@C̎w肪邩 + if (m_name[0] != 0x00) + { + addcmt(m_name, f_name); + + // w肪ꍇ + // t@C݂ȂERROR + if (SDFile::exists(f_name) == true) + { + // t@CI[v + file = new FILEIO(); + // file = filSD.open( f_name, FILE_READ ); + // if( true == file ){ + if (file->Fopen(create_sd_path(f_name), FILEIO_READ_BINARY)) + { + // f_lengthݒAr_count + f_length = file->FileLength(); + r_count = 0; + // ԃR[hM(OK) + snd1byte(0x00); + flg = true; + } + else + { + snd1byte(0xf0); + flg = false; + } + } + else + { + snd1byte(0xf1); + flg = false; + } + } + else + { + // t@C̎w肪Ȃꍇ + // t@CGhɂȂĂȂ + if (f_length > r_count) + { + snd1byte(0x00); + flg = true; + } + else + { + snd1byte(0xf1); + flg = false; + } + } + // ǂ΃t@CGh܂œǂݍ݂𑱍s + if (flg == true) + { + int rdata = 0; + + // wb_[oĂ܂œǂݔ΂ + while (rdata != 0x3a && rdata != 0xd3) + { + rdata = file->FgetUint8(); + r_count++; + } + // wb_[M + snd1byte(rdata); + // wb_[0xd3Ȃ瑱sAႦ΃G[ + if (rdata == 0xd3) + { + while (rdata == 0xd3) + { + rdata = file->FgetUint8(); + r_count++; + } + + // f[^M + int zcnt = 0; + int zdata = 1; + + snd1byte(rdata); + + // 0x0011‘܂œǂݍ݁AM + while (zcnt < 11) + { + rdata = file->FgetUint8(); + r_count++; + snd1byte(rdata); + if (rdata == 0x00) + { + zcnt++; + if (zdata != 0) + { + zcnt = 0; + } + } + zdata = rdata; + } + + // t@CGhɒBĂFILE CLOSE + if (f_length == r_count) + { + file->Fclose(); + delete file; + file = nullptr; + } + } + else + { + file->Fclose(); + delete file; + file = nullptr; + } + } +} + +// read file open +void sd_ropen(void) +{ + receive_name(f_name); + // t@C݂ȂERROR + if (SDFile::exists(f_name) == true) + { + // t@CI[v + // file = SD.open( f_name, FILE_READ ); + file = new FILEIO(); + if (file->Fopen(create_sd_path(f_name), FILEIO_READ_BINARY)) + { + // f_lengthݒAr_count + f_length = file->FileLength(); + r_count = 0; + // ԃR[hM(OK) + snd1byte(0x00); + } + else + { + snd1byte(0xf0); + } + } + else + { + snd1byte(0xf1); + } +} + +// write file append open +void sd_waopen(void) +{ + receive_name(w_name); + // t@CI[v + if (w_file != nullptr) + { + w_file->Fclose(); + } + // SD.open( w_name, FILE_WRITE ); + w_file = new FILEIO(); + if (w_file->Fopen(create_sd_path(w_name), FILEIO_WRITE_BINARY)) + { + // ԃR[hM(OK) + snd1byte(0x00); + } + else + { + snd1byte(0xf0); + } +} + +// write file new open +void sd_wnopen(void) +{ + receive_name(w_name); + if (w_file != nullptr) + { + w_file->Fclose(); + } + // t@C݂delete + if (SDFile::exists(w_name)) + { + SDFile::remove(w_name); + } + // t@CI[v + w_file = new FILEIO(); + if (w_file->Fopen(create_sd_path(w_name), FILEIO_WRITE_BINARY)) + { + // ԃR[hM(OK) + snd1byte(0x00); + } + else + { + snd1byte(0xf0); + } +} + +// 5ED9H +void sd_wdirect(void) +{ + if (w_file != nullptr) + { + w_body(); + w_file->Fclose(); + delete w_file; + w_file = nullptr; + // ԃR[hM(OK) + snd1byte(0x00); + } + else + { + snd1byte(0xf0); + } +} + +// write file close +void sd_wclose(void) +{ + w_file->Fclose(); + delete w_file; + w_file = nullptr; +} + +// write 1byte 5F2FH +void sd_w1byte(void) +{ + int rdata = rcv1byte(); + if (w_file != nullptr) + { + w_file->FputUint8(rdata); + // ԃR[hM(OK) + snd1byte(0x00); + } + else + { + snd1byte(0xf0); + } +} + +#ifdef _MSC_VER +unsigned __stdcall arduino_loop(void *lpx) +#else +void *arduino_loop(void *lpx) +#endif +{ + volatile PC80SD *p = (PC80SD *)lpx; + + current_pc80sd = (PC80SD *)p; + + while (p->request_terminate == false) + { + ((PC80SD *)p)->write_signals_thread(1, 0); + ((PC80SD *)p)->write_signals_thread(2, 0); + + uint8_t cmd = rcv1byte(); + + //// Serial.println(cmd,HEX); + if (eflg == false) + { + switch (cmd) + { + // 70h:PC-8001 CMTt@C SAVE + case 0x70: + //// Serial.println("CMT SAVE START"); + // ԃR[hM(OK) + snd1byte(0x00); + cmt_save(); + break; + // 71h:PC-8001 CMTt@C LOAD + case 0x71: + //// Serial.println("CMT LOAD START"); + // ԃR[hM(OK) + snd1byte(0x00); + cmt_load(); + break; + // 72h:PC-8001 5F9EH READ ONE BYTE FROM CMT + case 0x72: + //// Serial.println("CMT_5F9E START"); + // ԃR[hM(OK) + snd1byte(0x00); + cmt_5f9e(); + break; + // 73h:PC-8001 CMTt@C BASIC LOAD + case 0x73: + //// Serial.println("CMT BASIC LOAD START"); + // ԃR[hM(OK) + snd1byte(0x00); + bas_load(); + break; + // 74h:PC-8001 CMTt@C BASIC SAVE + case 0x74: + //// Serial.println("CMT BASIC SAVE START"); + // ԃR[hM(OK) + snd1byte(0x00); + bas_save(); + break; + // 75h:PC-8001 CMTt@C KILL + case 0x75: + //// Serial.println("CMT KILL START"); + // ԃR[hM(OK) + snd1byte(0x00); + bas_kill(); + break; + // 76h:PC-8001 SD FILE READ OPEN + case 0x76: + //// Serial.println("SD FILE READ OPEN START"); + // ԃR[hM(OK) + snd1byte(0x00); + sd_ropen(); + break; + // 77h:PC-8001 SD FILE WRITE APPEND OPEN + case 0x77: + //// Serial.println("SD FILE WRITE APPEND OPEN START"); + // ԃR[hM(OK) + snd1byte(0x00); + sd_waopen(); + break; + // 78h:PC-8001 SD FILE WRITE 1Byte + case 0x78: + //// Serial.println("SD FILE WRITE 1Byte START"); + // ԃR[hM(OK) + snd1byte(0x00); + sd_w1byte(); + break; + // 79h:PC-8001 SD FILE WRITE NEW OPEN + case 0x79: + //// Serial.println("SD FILE WRITE NEW OPEN START"); + // ԃR[hM(OK) + snd1byte(0x00); + sd_wnopen(); + break; + // 7Ah:PC-8001 SD WRITE 5ED9H + case 0x7A: + //// Serial.println("SD WRITE 5ED9H START"); + // ԃR[hM(OK) + snd1byte(0x00); + sd_wdirect(); + break; + // 7Bh:PC-8001 SD FILE WRITE CLOSE + case 0x7B: + //// Serial.println("SD FILE WRITE CLOSE START"); + // ԃR[hM(OK) + snd1byte(0x00); + sd_wclose(); + break; + + // 83hŃt@CXgo + case 0x83: + //// Serial.println("FILE LIST START"); + // ԃR[hM(OK) + snd1byte(0x00); + dirlist(); + break; + default: + // ԃR[hM(CMD ERROR) + snd1byte(0xF4); + } + } + else + { + // ԃR[hM(ERROR) + snd1byte(0xF0); + } + } + +#ifdef _MSC_VER + _endthreadex(0); + return 0; +#else + pthread_exit(NULL); + return NULL; +#endif +} + +PC80SD::~PC80SD() +{ + request_terminate = true; + thread_join(this); +} + +void PC80SD::initialize() +{ + InitializeCriticalSection(&signal_cs); + +#if defined(_WIN32) || defined(_WIN64) + threadHandle = _beginthreadex(NULL, 0, arduino_loop, this, 0, &threadID); +#else + pthread_create(&threadID, NULL, (void *(*)(void *)) & MyClass::thread_function, this); +#endif + strcpy(w_name, "default.dat"); + + // Ԃ̓eLg[(1.6MHz) + register_event(this, EVENT_TIMER, 0.625, true, NULL); +} + +void PC80SD::release() +{ +#if defined(_WIN32) || defined(_WIN64) + DeleteCriticalSection(&signal_cs); +#else + pthread_mutex_destroy(&mtx); +#endif +} + +void PC80SD::reset() +{ +} + +void PC80SD::write_signal(int id, uint32_t data, uint32_t mask) +{ + port[id].reg = (port[id].reg & ~mask) | (data & mask); +} + +void PC80SD::proc_signal() +{ +#if defined(_WIN32) || defined(_WIN64) + EnterCriticalSection(&signal_cs); +#else + pthread_mutex_lock(&mtx); +#endif + if(sleep_counter > 0) + { + sleep_counter--; + } + + // Queueɒ~ςꂽVOiCXbhŏ + while (!signalQueue.IsEmpty()) + { + SignalNode *node = signalQueue.Front(); + + write_signals(&port[node->ch].outputs, node->data); + + signalQueue.Dequeue(); + } + +#if defined(_WIN32) || defined(_WIN64) + LeaveCriticalSection(&signal_cs); +#else + pthread_mutex_unlock(&mtx); +#endif +} + +void PC80SD::write_signals_thread(int id, uint32_t data) +{ +#if defined(_WIN32) || defined(_WIN64) + EnterCriticalSection(&signal_cs); +#else + pthread_mutex_lock(&mtx); +#endif + if(id == -1) + { + sleep_counter = data; + } else { + signalQueue.Enqueue(id, data); + } + +#if defined(_WIN32) || defined(_WIN64) + LeaveCriticalSection(&signal_cs); +#else + pthread_mutex_unlock(&mtx); +#endif +} + +void PC80SD::event_callback(int event_id, int error) +{ + switch (event_id) + { + case EVENT_TIMER: + proc_signal(); + break; + } +} \ No newline at end of file diff --git a/gdemu/src/emulator/vm/pc80sd.h b/gdemu/src/emulator/vm/pc80sd.h new file mode 100644 index 0000000..8511007 --- /dev/null +++ b/gdemu/src/emulator/vm/pc80sd.h @@ -0,0 +1,136 @@ +/* + Skelton for retropc emulator + + Author : Takeda.Toshiya + Date : 2009.03.08- + + [ PC-8001(mk2)_SD ] +*/ + +#ifndef _PC80SD_H_ +#define _PC80SD_H_ + +#include "vm.h" +#include "../emu.h" +#include "device.h" + + +class SignalNode { +public: + int ch; + uint32_t data; + SignalNode* next; +}; + +class SignalQueue { +private: + SignalNode* front; + SignalNode* rear; + +public: + SignalQueue() : front(nullptr), rear(nullptr) {} + + ~SignalQueue() { + while (front != nullptr) { + SignalNode* temp = front; + front = front->next; + delete temp; + } + } + + void Enqueue(int ch, uint32_t data) { + SignalNode* newNode = new SignalNode; + newNode->ch = ch; + newNode->data = data; + newNode->next = nullptr; + + if (rear == nullptr) { + front = rear = newNode; + } else { + rear->next = newNode; + rear = newNode; + } + } + + void Dequeue() { + if (front == nullptr) + return; // Underflow case + + SignalNode* temp = front; + front = front->next; + + if (front == nullptr) + rear = nullptr; + + delete temp; + } + + SignalNode* Front() { + return front; + } + + bool IsEmpty() { + return front == nullptr; + } +}; + +class PC80SD : public DEVICE +{ +private: + void proc_signal(); +public: + SignalQueue signalQueue; + + struct { + uint8_t reg; + // output signals + outputs_t outputs; + } port[3]; + +#if defined(_WIN32) || defined(_WIN64) + unsigned threadID; + uintptr_t threadHandle; +#else + pthread_t threadID; +#endif + bool request_terminate; + int sleep_counter; + + PC80SD(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu) + { + for(int i = 0; i < 3; i++) { + initialize_output_signals(&port[i].outputs); + port[i].reg = 0;//0xff; + } + request_terminate = false; + sleep_counter = 0; + + set_device_name(_T("PC8001(mk2)_SD")); + } + ~PC80SD(); + + // common functions + void initialize(); + void release(); + void reset(); + void write_signal(int id, uint32_t data, uint32_t mask); + void event_callback(int event_id, int error); + + void write_signals_thread(int id, uint32_t data); + + void set_context_port_a(DEVICE* device, int id, uint32_t mask, int shift) + { + register_output_signal(&port[0].outputs, device, id, mask, shift); + } + void set_context_port_b(DEVICE* device, int id, uint32_t mask, int shift) + { + register_output_signal(&port[1].outputs, device, id, mask, shift); + } + void set_context_port_c(DEVICE* device, int id, uint32_t mask, int shift) + { + register_output_signal(&port[2].outputs, device, id, mask, shift); + } +}; + +#endif + diff --git a/gdemu/src/emulator/vm/pc8801/pc88.cpp b/gdemu/src/emulator/vm/pc8801/pc88.cpp index f0b9392..eed2afa 100644 --- a/gdemu/src/emulator/vm/pc8801/pc88.cpp +++ b/gdemu/src/emulator/vm/pc8801/pc88.cpp @@ -351,6 +351,23 @@ void PC88::initialize() fio->Fclose(); } #endif + +#if defined(SUPPORT_PC80_SDCARD) + if(fio->Fopen(create_local_path(_T("EXT_ROM_SHIFT_OFF.bin")), FILEIO_READ_BINARY)) { + fio->Fread(n80sdrom, 0x2000, 1); + fio->Fclose(); + } else if(fio->Fopen(create_local_path(_T("EXT_ROM_SHIFT_ON.bin")), FILEIO_READ_BINARY)) { + fio->Fread(n80sdrom, 0x2000, 1); + fio->Fclose(); + } else if(fio->Fopen(create_local_path(_T("EXT_ROM_A_OFF.bin")), FILEIO_READ_BINARY)) { + fio->Fread(n80sdrom, 0x2000, 1); + fio->Fclose(); + } else if(fio->Fopen(create_local_path(_T("EXT_ROM_A_ON.bin")), FILEIO_READ_BINARY)) { + fio->Fread(n80sdrom, 0x2000, 1); + fio->Fclose(); + } +#endif + #if defined(_PC8001SR) if(fio->Fopen(create_local_path(_T("N80_3.ROM")), FILEIO_READ_BINARY)) { fio->Fread(n80srrom, 0xa000, 1); @@ -525,7 +542,7 @@ void PC88::initialize() // initialize cmt cmt_fio = new FILEIO(); cmt_play = cmt_rec = false; - + register_frame_event(this); register_vline_event(this); register_event(this, EVENT_TIMER, 1000000.0 / 600.0, true, NULL); @@ -1270,6 +1287,21 @@ void PC88::write_io8(uint32_t addr, uint32_t data) } break; #endif +#ifdef SUPPORT_PC80_SDCARD + // for PC-8001mk2_SD + case 0x7c: // PPI_A + d_sdcard->write_io8(0, data); + break; + case 0x7d: // PPI_B + d_sdcard->write_io8(1, data); + break; + case 0x7e: // PPI_C + d_sdcard->write_io8(2, data); + break; + case 0x7f: // PPI_R + d_sdcard->write_io8(3, data); + break; +#endif #else case 0x71: if(mod & 0x03) { @@ -1762,6 +1794,20 @@ uint32_t PC88::read_io8_debug(uint32_t addr) } break; #endif + +#ifdef SUPPORT_PC80_SDCARD + // for PC-8001mk2_SD + case 0x7c: // PPI_A + return d_sdcard->read_io8(0); + case 0x7d: // PPI_B + return d_sdcard->read_io8(1); + case 0x7e: // PPI_C + return d_sdcard->read_io8(2); + case 0x7f: // PPI_R + return d_sdcard->read_io8(3); +#endif + + #ifdef SUPPORT_PC88_HMB20 // case 0x88: case 0x89: @@ -2241,7 +2287,12 @@ void PC88::update_n80_read() SET_BANK_R(0x6000, 0x7fff, n80erom); } else #endif + +#ifdef SUPPORT_PC80_SDCARD + SET_BANK_R(0x6000, 0x7fff, n80sdrom); +#else SET_BANK_R(0x6000, 0x7fff, rdmy); +#endif return; } #endif diff --git a/gdemu/src/emulator/vm/pc8801/pc88.h b/gdemu/src/emulator/vm/pc8801/pc88.h index f634b62..578bd48 100644 --- a/gdemu/src/emulator/vm/pc8801/pc88.h +++ b/gdemu/src/emulator/vm/pc8801/pc88.h @@ -161,6 +161,9 @@ class PC88 : public DEVICE #ifdef SUPPORT_M88_DISKDRV DEVICE *d_diskio; #endif +#ifdef SUPPORT_PC80_SDCARD + DEVICE *d_sdcard; +#endif uint8_t* rbank[16]; uint8_t* wbank[16]; @@ -183,6 +186,9 @@ class PC88 : public DEVICE #if defined(_PC8001MK2) || defined(_PC8001SR) uint8_t n80erom[0x2000]; #endif +#if defined(SUPPORT_PC80_SDCARD) + uint8_t n80sdrom[0x2000]; +#endif #if defined(_PC8001SR) uint8_t n80srrom[0xa000]; uint8_t hiragana[0x200]; @@ -352,6 +358,12 @@ class PC88 : public DEVICE void release_tape(); bool check_data_carrier(); + +#ifdef SUPPORT_PC80_SDCARD + FILEIO *sdcard_fio; + _TCHAR sd_file_path[_MAX_PATH]; + uint8_t sd_buffer[CMT_BUFFER_SIZE]; +#endif // beep/sing bool beep_on, beep_signal, sing_signal; @@ -562,6 +574,12 @@ class PC88 : public DEVICE { d_diskio = device; } +#endif +#ifdef SUPPORT_PC80_SDCARD + void set_context_sdcard(DEVICE* device) + { + d_sdcard = device; + } #endif void key_down(int code, bool repeat); bool get_caps_locked() diff --git a/gdemu/src/emulator/vm/pc8801/pc8801.cpp b/gdemu/src/emulator/vm/pc8801/pc8801.cpp index f7b59d4..949b582 100644 --- a/gdemu/src/emulator/vm/pc8801/pc8801.cpp +++ b/gdemu/src/emulator/vm/pc8801/pc8801.cpp @@ -69,6 +69,10 @@ #include "diskio.h" #endif +#ifdef SUPPORT_PC80_SDCARD +#include "../pc80sd.h" +#endif + #include "pc88.h" // ---------------------------------------------------------------------------- @@ -369,6 +373,12 @@ VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu) pc88diskio = NULL; } #endif + +#ifdef SUPPORT_PC80_SDCARD + pc80sd_pio = new I8255(this, emu); + pc80sd_pio->set_device_name(_T("8255 PIO (PC-8001(mkII)_SD board)")); + pc80sd_dev = new PC80SD(this, emu); +#endif // set cpu device contexts #ifdef SUPPORT_PC88_HIGH_CLOCK @@ -495,6 +505,15 @@ VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu) if(config.dipswitch & DIPSWITCH_M88_DISKDRV) { pc88->set_context_diskio(pc88diskio); } +#endif +#ifdef SUPPORT_PC80_SDCARD + pc88->set_context_sdcard(pc80sd_pio); + pc80sd_pio->clear_ports_by_cmdreg = true; + pc80sd_pio->set_context_port_a(pc80sd_dev, SIG_I8255_PORT_A, 0xFF, 0); + pc80sd_pio->set_context_port_c(pc80sd_dev, SIG_I8255_PORT_C, 0x0F, 0); + + pc80sd_dev->set_context_port_b(pc80sd_pio, SIG_I8255_PORT_B, 0xFF, 0); + pc80sd_dev->set_context_port_c(pc80sd_pio, SIG_I8255_PORT_C, 0xF0, 0); #endif pc88cpu->set_context_mem(pc88); pc88cpu->set_context_io(pc88); @@ -677,6 +696,10 @@ void VM::reset() pc88pio_sub->write_signal(SIG_I8255_PORT_C, 0, 0xff); } pc88pio->write_signal(SIG_I8255_PORT_C, 0, 0xff); + +#ifdef SUPPORT_PC80_SDCARD + pc80sd_pio->write_signal(SIG_I8255_PORT_C, 0, 0xff); +#endif } void VM::run() diff --git a/gdemu/src/emulator/vm/pc8801/pc8801.h b/gdemu/src/emulator/vm/pc8801/pc8801.h index d89cc7f..f23c114 100644 --- a/gdemu/src/emulator/vm/pc8801/pc8801.h +++ b/gdemu/src/emulator/vm/pc8801/pc8801.h @@ -112,6 +112,7 @@ #define PC88_EXRAM_BANKS 1 #define SUPPORT_PC88_FDD_8INCH #define SUPPORT_M88_DISKDRV + #define SUPPORT_PC80_SDCARD #elif defined(_PC8001) // #define SUPPORT_PC88_KANJI1 // #define SUPPORT_PC88_KANJI2 @@ -342,6 +343,10 @@ class MEMORY; class DiskIO; #endif +#ifdef SUPPORT_PC80_SDCARD +class PC80SD; +#endif + class PC88; class VM : public VM_TEMPLATE @@ -418,6 +423,11 @@ class VM : public VM_TEMPLATE #ifdef SUPPORT_M88_DISKDRV DiskIO* pc88diskio; #endif + +#ifdef SUPPORT_PC80_SDCARD + I8255* pc80sd_pio; + PC80SD* pc80sd_dev; +#endif PC88* pc88; diff --git a/gdemu/src/gdemu.cpp b/gdemu/src/gdemu.cpp index 5dcda0a..cc602f8 100644 --- a/gdemu/src/gdemu.cpp +++ b/gdemu/src/gdemu.cpp @@ -81,6 +81,36 @@ static void file_copy(String from, String to) } } +static void folder_copy(String folder_name) +{ + + Ref dir = DirAccess::open("user://"); + if(!dir->dir_exists(folder_name)) + { + dir->make_dir(folder_name); + } + // fromフォルダ内の全てのファイルをtoフォルダにコピーする + dir = DirAccess::open("res://" + folder_name); + dir->list_dir_begin(); + String file = dir->get_next(); + while(file != "") + { + String from_file = "res://" + folder_name + "/" + file; + String to_file = "user://" + folder_name + "/" + file; + if(dir->current_is_dir()) + { + // フォルダは無視 + file = dir->get_next(); + continue; + } + else + { + // ファイルならコピー + dir->copy(from_file, to_file); + } + file = dir->get_next(); + } +} void GDEmu::setup() { @@ -149,7 +179,13 @@ void GDEmu::init() { #if defined(_PC8001MK2) file_copy("res://N80_2.ROM", "user://N80_2.ROM"); + file_copy("res://N80_3.ROM", "user://N80_3.ROM"); file_copy("res://KANJI1.ROM", "user://KANJI1.ROM"); + file_copy("res://EXT_ROM_SHIFT_OFF.bin", "user://EXT_ROM_SHIFT_OFF.bin"); + file_copy("res://EXT_ROM_SHIFT_ON.bin", "user://EXT_ROM_SHIFT_ON.bin"); + file_copy("res://EXT_ROM_A_OFF.bin", "user://EXT_ROM_A_OFF.bin"); + file_copy("res://EXT_ROM_A_ON.bin", "user://EXT_ROM_A_ON.bin"); + folder_copy("SD"); #endif // フロッピーアクセス音 From 41e54817a199000954aa50ec53adebda5606bdc7 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogino Date: Sun, 6 Aug 2023 23:06:18 +0900 Subject: [PATCH 3/9] =?UTF-8?q?=E3=83=9E=E3=83=AB=E3=83=81=E3=82=B9?= =?UTF-8?q?=E3=83=AC=E3=83=83=E3=83=89=E6=8C=AB=E6=8A=98=E7=89=88=E3=80=82?= =?UTF-8?q?=E9=9D=9E=E3=83=9E=E3=83=AB=E3=83=81=E3=82=B9=E3=83=AC=E3=83=83?= =?UTF-8?q?=E3=83=89=E3=81=AB=E3=81=99=E3=82=8B=E4=BA=88=E5=AE=9A=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gdemu/src/emulator/vm/pc80sd.cpp | 215 ++++++++++++++++++++---- gdemu/src/emulator/vm/pc80sd.h | 29 ++++ gdemu/src/emulator/vm/pc8801/diskio.cpp | 2 +- gdemu/src/emulator/vm/pc8801/diskio.h | 4 + gdemu/src/emulator/vm/pc8801/pc88.cpp | 9 +- gdemu/src/emulator/vm/pc8801/pc8801.h | 4 +- gdemu/src/gdemu.cpp | 35 ++-- 7 files changed, 250 insertions(+), 48 deletions(-) diff --git a/gdemu/src/emulator/vm/pc80sd.cpp b/gdemu/src/emulator/vm/pc80sd.cpp index 6c7c8bf..8657dee 100644 --- a/gdemu/src/emulator/vm/pc80sd.cpp +++ b/gdemu/src/emulator/vm/pc80sd.cpp @@ -9,6 +9,11 @@ #include "pc80sd.h" #include "../fileio.h" +#if !(defined(_WIN32) || defined(_WIN64)) +#include +#include +#endif + #define EVENT_TIMER 1 #define SIG_I8255_PORT_A 0 @@ -17,6 +22,13 @@ PC80SD *current_pc80sd; +enum { + NOCHECK = 0, + CHECK_LOW, + CHECK_HIGH, +}; +int current_check = NOCHECK; + #if defined(_WIN32) || defined(_WIN64) CRITICAL_SECTION signal_cs; #else @@ -83,7 +95,7 @@ class SDFile HANDLE hFind = INVALID_HANDLE_VALUE; #else DIR *dir; - struct dirent *dp; + struct dirent *ent; #endif SDFileEntry currentEntry; @@ -92,6 +104,10 @@ class SDFile { memset(base_path, 0, sizeof(base_path)); } + ~SDFile() + { + close(); + } bool open(const char *path); SDFileEntry openNextFile(); void rewindDirectory(); @@ -183,12 +199,14 @@ SDFileEntry SDFile::openNextFile() #else bool updated = false; - while((ent = readdir(dir)) != NULL) + char full_path[PATH_MAX]; + if(dir != nullptr) { struct stat st; while ((ent = readdir(dir)) != NULL) { - stat(ent->d_name, &st); + snprintf(full_path, sizeof(full_path), "%s/%s", base_path, ent->d_name); + stat(full_path, &st); if (S_ISDIR(st.st_mode)) { continue; } else if(S_ISREG(st.st_mode)) { @@ -205,7 +223,11 @@ SDFileEntry SDFile::openNextFile() { SDFileEntry invalidEntry; currentEntry = invalidEntry; - closedir(dir); + if(dir != nullptr) + { + closedir(dir); + dir = nullptr; + } } #endif return result; @@ -242,12 +264,14 @@ bool SDFile::open(const char *path) break; } while (FindNextFile(hFind, &ffd) != 0); #else + char full_path[PATH_MAX]; if ((dir = opendir(path)) != NULL) { struct stat st; while ((ent = readdir(dir)) != NULL) { - stat(ent->d_name, &st); + snprintf(full_path, sizeof(full_path), "%s/%s", path, ent->d_name); + stat(full_path, &st); if (S_ISDIR(st.st_mode)) { continue; } else if(S_ISREG(st.st_mode)) { @@ -266,6 +290,11 @@ void SDFile::close() #if defined(_WIN32) || defined(_WIN64) FindClose(hFind); #else + if(dir != nullptr) + { + closedir(dir); + dir = nullptr; + } #endif } @@ -306,7 +335,7 @@ void thread_join(volatile PC80SD *p) WaitForSingleObject((HANDLE)p->threadHandle, INFINITE); CloseHandle((HANDLE)p->threadHandle); #else - pthread_join(threadID, NULL); + pthread_join(p->threadID, NULL); #endif } @@ -322,11 +351,17 @@ void thread_yield() void thread_sleep(int timer_count) { + // pthread_mutex_lock(&mtx); current_pc80sd->write_signals_thread(-1, timer_count); - while(current_pc80sd->sleep_counter > 0) + // printf("thread_sleep: start %d\n", timer_count); + // pthread_mutex_unlock(&mtx); + while(current_pc80sd->sleep_counter > 0 && !current_pc80sd->request_terminate) { + // printf("thread_sleep: rest %d\n", current_pc80sd->sleep_counter); thread_yield(); + // printf("thread_sleep: rest2 %d\n", current_pc80sd->sleep_counter); } + // printf("thread_sleep: rest end %d\n", current_pc80sd->sleep_counter); //#if defined(_WIN32) || defined(_WIN64) // // Windows̏ꍇ @@ -339,9 +374,22 @@ void thread_sleep(int timer_count) uint8_t rcv4bit() { + printf("rcv4bit\n"); + if(current_pc80sd->request_terminate) + { + return 0; + } + + printf("rcv4bit: high wait\n"); // HIGHɂȂ܂Ń[v - while ((current_pc80sd->port[2].reg & 0x4) == 0 && !current_pc80sd->request_terminate) + if(!(current_pc80sd->port[2].reg & 0x4)) + { + current_check = CHECK_HIGH; + } + // while ((current_pc80sd->port[2].reg & 0x4) == 0 && !current_pc80sd->request_terminate) + while (current_check != NOCHECK && !current_pc80sd->request_terminate) { + // printf("rcv4bit: high wait\n"); thread_yield(); } if (current_pc80sd->request_terminate) @@ -352,12 +400,17 @@ uint8_t rcv4bit() // M uint8_t j_data = current_pc80sd->port[0].reg & 0xf; + printf("rcv4bit: low wait\n"); + // LOWɂȂ܂Ń[v + if((current_pc80sd->port[2].reg & 0x4)) + { + current_check = CHECK_LOW; + } // FLGZbg current_pc80sd->write_signals_thread(2, 0x80); - - // LOWɂȂ܂Ń[v - while ((current_pc80sd->port[2].reg & 0x4) != 0 && !current_pc80sd->request_terminate) + while (current_check != NOCHECK && !current_pc80sd->request_terminate) { + // printf("rcv4bit: low wait\n"); thread_yield(); } if (current_pc80sd->request_terminate) @@ -368,27 +421,48 @@ uint8_t rcv4bit() // FLGZbg current_pc80sd->write_signals_thread(2, 0x00); - // rcv1byteꍇLOW̃`FbNZ80łȂ̂ - thread_sleep(100); + + // Ԍv̂߂Ɍ݂̎Ԃۑ + struct timespec start_time, end_time; + clock_gettime(CLOCK_MONOTONIC, &start_time); + + // rcv1byteꍇLOW̃`FbNZ80łȂ̂łȂɑ҂Ă + printf("receive end wait start\n"); + thread_sleep(16000); + printf("receive end wait end\n"); + clock_gettime(CLOCK_MONOTONIC, &end_time); + double elapsed = (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_nsec - start_time.tv_nsec) * 1e-9; + + printf("Elapsed time: %.9f seconds\n", elapsed); + + //printf("rcv4bit end\n"); return (j_data); } // 1BYTEM -void snd1byte(byte i_data) +void snd1byte(uint8_t i_data) { + //printf("snd1byte\n"); if (current_pc80sd->request_terminate) { return; } // ʃrbg8rbgZbg current_pc80sd->write_signals_thread(1, i_data); + + // HIGHɂȂ܂Ń[v + if(!(current_pc80sd->port[2].reg & 0x4)) + { + current_check = CHECK_HIGH; + } // FLGPINHIGH current_pc80sd->write_signals_thread(2, 0x80); - // HIGHɂȂ܂Ń[v - while ((current_pc80sd->port[2].reg & 0x4) == 0 && !current_pc80sd->request_terminate) + //printf("snd1byte high loop\n"); + while (current_check != NOCHECK && !current_pc80sd->request_terminate) { + // printf("snd1byte: high wait\n"); thread_yield(); } if (current_pc80sd->request_terminate) @@ -396,21 +470,33 @@ void snd1byte(byte i_data) return; } + // LOWɂȂ܂Ń[v + if((current_pc80sd->port[2].reg & 0x4)) + { + current_check = CHECK_LOW; + } current_pc80sd->write_signals_thread(2, 0x00); - // LOWɂȂ܂Ń[v - while ((current_pc80sd->port[2].reg & 0x4) != 0 && !current_pc80sd->request_terminate) + printf("snd1byte low loop\n"); + //while ((current_pc80sd->port[2].reg & 0x4) != 0 && !current_pc80sd->request_terminate) + while (current_check != NOCHECK && !current_pc80sd->request_terminate) { + // printf("snd1byte: low wait\n"); thread_yield(); } if (current_pc80sd->request_terminate) { return; } + printf("snd1byte end\n"); } uint8_t rcv1byte() { + if(current_pc80sd->request_terminate) + { + return 0; + } uint8_t i_data = 0; i_data = rcv4bit() * 16; i_data = i_data + rcv4bit(); @@ -420,18 +506,22 @@ uint8_t rcv1byte() // SD-CARDFILELIST void dirlist() { + printf("dirlist\n"); // r擾 32+1܂ for (unsigned int lp1 = 0; lp1 <= 32; lp1++) { c_name[lp1] = rcv1byte(); } + printf("dirlist 2\n"); SDFile file; bool result = file.open(create_local_path(sd_folder_name)); if (result) { // ԃR[hM(OK) + printf("send ok\n"); snd1byte(0x00); + printf("send ok 2\n"); SDFileEntry entry = file.openNextFile(); int cntl2 = 0; @@ -566,7 +656,7 @@ void receive_name(char *f_name) // MONITOR LR}h .CMT LOAD void cmt_load() { - boolean flg = false; + bool flg = false; // DOSt@C擾 receive_name(m_name); // t@C̎w肪邩 @@ -724,7 +814,7 @@ void cmt_5f9e(void) void w_body(void) { - byte r_data, csum; + uint8_t r_data, csum; // wb_[ 0x3A w_file->FputUint8(char(0x3A)); // X^[gAhX擾A @@ -790,7 +880,7 @@ void w_body(void) // MONITOR WR}h .CMT SAVE void cmt_save(void) { - byte r_data, csum; + uint8_t r_data, csum; // DOSt@C擾 receive_name(m_name); // t@C̎w肪΃G[ @@ -1178,6 +1268,7 @@ unsigned __stdcall arduino_loop(void *lpx) void *arduino_loop(void *lpx) #endif { + printf("arduino_loop start\n"); volatile PC80SD *p = (PC80SD *)lpx; current_pc80sd = (PC80SD *)p; @@ -1186,8 +1277,15 @@ void *arduino_loop(void *lpx) { ((PC80SD *)p)->write_signals_thread(1, 0); ((PC80SD *)p)->write_signals_thread(2, 0); + thread_sleep(1000); + printf("command wait...\n"); uint8_t cmd = rcv1byte(); + printf("command received %d\n", (int)cmd); + if(p->request_terminate) + { + break; + } //// Serial.println(cmd,HEX); if (eflg == false) @@ -1283,7 +1381,9 @@ void *arduino_loop(void *lpx) case 0x83: //// Serial.println("FILE LIST START"); // ԃR[hM(OK) + printf("dirlist ok send start\n"); snd1byte(0x00); + printf("dirlist ok send end\n"); dirlist(); break; default: @@ -1298,6 +1398,7 @@ void *arduino_loop(void *lpx) } } + printf("PC80SD thread end\n"); #ifdef _MSC_VER _endthreadex(0); return 0; @@ -1309,23 +1410,33 @@ void *arduino_loop(void *lpx) PC80SD::~PC80SD() { + printf("PC80SD destructor\n"); request_terminate = true; thread_join(this); + + printf("PC80SD destructor end\n"); + release(); + printf("PC80SD destructor end 2\n"); } void PC80SD::initialize() { - InitializeCriticalSection(&signal_cs); - + printf("PC80SD initialize\n"); #if defined(_WIN32) || defined(_WIN64) + InitializeCriticalSection(&signal_cs); threadHandle = _beginthreadex(NULL, 0, arduino_loop, this, 0, &threadID); #else - pthread_create(&threadID, NULL, (void *(*)(void *)) & MyClass::thread_function, this); + pthread_mutex_init(&mtx, NULL); + pthread_create(&threadID, NULL, (void *(*)(void *)) & arduino_loop, this); #endif strcpy(w_name, "default.dat"); // Ԃ̓eLg[(1.6MHz) - register_event(this, EVENT_TIMER, 0.625, true, NULL); + register_event(this, EVENT_TIMER, 0.625, true, ®ister_id); + + signalQueue.Clear(); + request_terminate = false; + sleep_counter = 0; } void PC80SD::release() @@ -1339,10 +1450,36 @@ void PC80SD::release() void PC80SD::reset() { + printf("reset\n"); + + request_terminate = true; + thread_join(this); + + release(); + + initialize(); + printf("initialize end\n"); } void PC80SD::write_signal(int id, uint32_t data, uint32_t mask) { + if(id == 2) + { + if(current_check == CHECK_HIGH) + { + if(data != 0) + { + current_check = NOCHECK; + } + } else if(current_check == CHECK_LOW) + { + if(data == 0) + { + current_check = NOCHECK; + } + } + } + printf("write signal(from Z80) %d %x %x\n", id, data, mask); port[id].reg = (port[id].reg & ~mask) | (data & mask); } @@ -1353,20 +1490,32 @@ void PC80SD::proc_signal() #else pthread_mutex_lock(&mtx); #endif - if(sleep_counter > 0) + // Queueɒ~ςꂽVOiCXbhŏ + bool queue_proc = false; + if(!signalQueue.IsEmpty()) { - sleep_counter--; + printf("Queue proc start ------------\n"); + queue_proc = true; } - - // Queueɒ~ςꂽVOiCXbhŏ while (!signalQueue.IsEmpty()) { SignalNode *node = signalQueue.Front(); + printf("signalQueue.Dequeue(to Z80) %d %d\n", node->ch, node->data); write_signals(&port[node->ch].outputs, node->data); signalQueue.Dequeue(); } + if(queue_proc) + { + printf("Queue proc end ------------\n"); + } + + if(sleep_counter > 0) + { + sleep_counter--; + // printf("sleep dec %d\n", sleep_counter); + } #if defined(_WIN32) || defined(_WIN64) LeaveCriticalSection(&signal_cs); @@ -1385,8 +1534,16 @@ void PC80SD::write_signals_thread(int id, uint32_t data) if(id == -1) { sleep_counter = data; + // printf("sleep counter set %d\n", data); } else { + // if(!signalQueue.IsEmpty()) + // { + // printf("write_signals_thread: has queue\n"); + // SignalNode *node = signalQueue.Front(); + // printf("write_signals_thread: front: %d : %d\n", node->ch, node->data); + // } signalQueue.Enqueue(id, data); + printf("signalQueue.Enqueue(to Z80) %d %d\n", id, data); } #if defined(_WIN32) || defined(_WIN64) diff --git a/gdemu/src/emulator/vm/pc80sd.h b/gdemu/src/emulator/vm/pc80sd.h index 8511007..0d75b6b 100644 --- a/gdemu/src/emulator/vm/pc80sd.h +++ b/gdemu/src/emulator/vm/pc80sd.h @@ -14,6 +14,10 @@ #include "../emu.h" #include "device.h" +#if !(defined(_WIN32) || defined(_WIN64)) +#include +#endif + class SignalNode { public: @@ -69,6 +73,16 @@ class SignalQueue { return front; } + void Clear() + { + while (front != nullptr) { + SignalNode* temp = front; + front = front->next; + delete temp; + } + rear = nullptr; + } + bool IsEmpty() { return front == nullptr; } @@ -78,8 +92,23 @@ class PC80SD : public DEVICE { private: void proc_signal(); + + int state; + int sub_state; + int result_value; + int send_value; + int sd_command; + uint8_t receive_datas[256]; + uint8_t send_datas[65536]; + int send_datas_count; + int send_datas_index; + int receive_datas_count; + int receive_datas_index; + int wait_count; + Stack stateStack; public: SignalQueue signalQueue; + int register_id; struct { uint8_t reg; diff --git a/gdemu/src/emulator/vm/pc8801/diskio.cpp b/gdemu/src/emulator/vm/pc8801/diskio.cpp index 30256cb..58d71de 100644 --- a/gdemu/src/emulator/vm/pc8801/diskio.cpp +++ b/gdemu/src/emulator/vm/pc8801/diskio.cpp @@ -179,7 +179,7 @@ void DiskIO::CmdReadFile() if (file->Fopen(create_absolute_path(char_to_tchar((char*) filename)), FILEIO_READ_BINARY)) { file->Fseek(0, FILEIO_SEEK_END); - size = min(0xffff, file->Ftell()); + size = min((unsigned int)0xffff, (unsigned int)file->Ftell()); file->Fseek(0, FILEIO_SEEK_SET); buf[0] = size & 0xff; buf[1] = (size >> 8) & 0xff; diff --git a/gdemu/src/emulator/vm/pc8801/diskio.h b/gdemu/src/emulator/vm/pc8801/diskio.h index 363d03b..59c0f38 100644 --- a/gdemu/src/emulator/vm/pc8801/diskio.h +++ b/gdemu/src/emulator/vm/pc8801/diskio.h @@ -27,6 +27,10 @@ class FILEIO; +#ifndef MAX_PATH +#define MAX_PATH 260 +#endif + // --------------------------------------------------------------------------- class DiskIO : public DEVICE diff --git a/gdemu/src/emulator/vm/pc8801/pc88.cpp b/gdemu/src/emulator/vm/pc8801/pc88.cpp index eed2afa..8c1e52c 100644 --- a/gdemu/src/emulator/vm/pc8801/pc88.cpp +++ b/gdemu/src/emulator/vm/pc8801/pc88.cpp @@ -264,7 +264,14 @@ static const int key_conv_table[][3] = { }; static const uint8_t intr_mask2_table[8] = { - ~7, ~3, ~5, ~1, ~6, ~2, ~4, ~0 + (uint8_t)~7, + (uint8_t)~3, + (uint8_t)~5, + (uint8_t)~1, + (uint8_t)~6, + (uint8_t)~2, + (uint8_t)~4, + (uint8_t)~0 }; void PC88::initialize() diff --git a/gdemu/src/emulator/vm/pc8801/pc8801.h b/gdemu/src/emulator/vm/pc8801/pc8801.h index f23c114..80e2627 100644 --- a/gdemu/src/emulator/vm/pc8801/pc8801.h +++ b/gdemu/src/emulator/vm/pc8801/pc8801.h @@ -179,7 +179,7 @@ #define USE_COMPACT_DISC 1 #endif #define USE_KEY_LOCKED -// slow enough for N88-{BASIC +// slow enough for N88-���{��BASIC #define USE_AUTO_KEY 8 #define USE_AUTO_KEY_RELEASE 10 #define USE_AUTO_KEY_NUMPAD @@ -245,7 +245,7 @@ #else #define USE_PRINTER_TYPE 3 #endif -#define USE_DEBUGGER +//#define USE_DEBUGGER #define USE_STATE #include "../../common.h" diff --git a/gdemu/src/gdemu.cpp b/gdemu/src/gdemu.cpp index cc602f8..bc55d94 100644 --- a/gdemu/src/gdemu.cpp +++ b/gdemu/src/gdemu.cpp @@ -83,7 +83,6 @@ static void file_copy(String from, String to) static void folder_copy(String folder_name) { - Ref dir = DirAccess::open("user://"); if(!dir->dir_exists(folder_name)) { @@ -91,24 +90,27 @@ static void folder_copy(String folder_name) } // fromフォルダ内の全てのファイルをtoフォルダにコピーする dir = DirAccess::open("res://" + folder_name); - dir->list_dir_begin(); - String file = dir->get_next(); - while(file != "") + if(dir->get_open_error() == Error::OK) { - String from_file = "res://" + folder_name + "/" + file; - String to_file = "user://" + folder_name + "/" + file; - if(dir->current_is_dir()) + dir->list_dir_begin(); + String file = dir->get_next(); + while(file != "") { - // フォルダは無視 + String from_file = "res://" + folder_name + "/" + file; + String to_file = "user://" + folder_name + "/" + file; + if(dir->current_is_dir()) + { + // フォルダは無視 + file = dir->get_next(); + continue; + } + else + { + // ファイルならコピー + dir->copy(from_file, to_file); + } file = dir->get_next(); - continue; - } - else - { - // ファイルならコピー - dir->copy(from_file, to_file); } - file = dir->get_next(); } } @@ -181,6 +183,9 @@ void GDEmu::init() { file_copy("res://N80_2.ROM", "user://N80_2.ROM"); file_copy("res://N80_3.ROM", "user://N80_3.ROM"); file_copy("res://KANJI1.ROM", "user://KANJI1.ROM"); +#endif + +#ifdef SUPPORT_PC80_SDCARD file_copy("res://EXT_ROM_SHIFT_OFF.bin", "user://EXT_ROM_SHIFT_OFF.bin"); file_copy("res://EXT_ROM_SHIFT_ON.bin", "user://EXT_ROM_SHIFT_ON.bin"); file_copy("res://EXT_ROM_A_OFF.bin", "user://EXT_ROM_A_OFF.bin"); From cb539c43c9ecd02a537a335e024dabfe1daa5eb0 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogino Date: Mon, 7 Aug 2023 14:06:05 +0900 Subject: [PATCH 4/9] =?UTF-8?q?=E3=82=B9=E3=83=AC=E3=83=83=E3=83=89?= =?UTF-8?q?=E3=81=A0=E3=81=A8=E5=AE=89=E5=AE=9A=E3=81=97=E3=81=AA=E3=81=84?= =?UTF-8?q?=E3=81=AE=E3=81=A7=E9=9D=9E=E3=82=B9=E3=83=AC=E3=83=83=E3=83=89?= =?UTF-8?q?=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gdemu/src/emulator/vm/pc80sd.cpp | 2683 +++++++++++++++++------------- gdemu/src/emulator/vm/pc80sd.h | 203 ++- 2 files changed, 1712 insertions(+), 1174 deletions(-) diff --git a/gdemu/src/emulator/vm/pc80sd.cpp b/gdemu/src/emulator/vm/pc80sd.cpp index 8657dee..7cb8767 100644 --- a/gdemu/src/emulator/vm/pc80sd.cpp +++ b/gdemu/src/emulator/vm/pc80sd.cpp @@ -6,13 +6,10 @@ [ PC-8001(mk2)_SD ] */ + #include "pc80sd.h" #include "../fileio.h" -#if !(defined(_WIN32) || defined(_WIN64)) -#include -#include -#endif #define EVENT_TIMER 1 @@ -22,18 +19,38 @@ PC80SD *current_pc80sd; -enum { - NOCHECK = 0, - CHECK_LOW, - CHECK_HIGH, -}; -int current_check = NOCHECK; +static uint8_t cr_data[2] = {0x0d,0x00}; +static uint8_t end_data[2] = {0xff,0x00}; -#if defined(_WIN32) || defined(_WIN64) -CRITICAL_SECTION signal_cs; -#else -pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; -#endif +enum pc80sd_state +{ + PC80SD_INITIALIZE = 0, + PC80SD_WAIT_COMMAND, + + PC80SD_RCV4BIT, + PC80SD_RCV1BYTE, + PC80SD_SND1BYTE, + PC80SD_RCVBYTES, + PC80SD_SNDBYTES, + PC80SD_RCVNAME, + PC80SD_WBODY, + + PC80SD_DIRLIST = 0x83, + PC80SD_CMT_SAVE = 0x70, + PC80SD_CMT_LOAD = 0x71, + PC80SD_CMT_5F9E = 0x72, + PC80SD_BAS_LOAD = 0x73, + PC80SD_BAS_SAVE = 0x74, + PC80SD_BAS_KILL = 0x75, + PC80SD_SD_ROPEN = 0x76, + PC80SD_SD_WAOPEN = 0x77, + PC80SD_SD_W1BYTE = 0x78, + PC80SD_SD_WNOPEN = 0x79, + PC80SD_SD_WDIRECT = 0x7A, + PC80SD_SD_WCLOSE = 0x7B, + + PC80SD_WAIT, +}; // ۑtH_ const _TCHAR *sd_folder_name = _T("SD"); @@ -50,72 +67,6 @@ unsigned int s_adrs, e_adrs, w_length, w_len1, w_len2, s_adrs1, s_adrs2, b_lengt FILEIO *file, *w_file; -class SDFileEntry -{ -private: - bool _isValid; - char name[1024]; - -public: - SDFileEntry() - { - invalidate(); - } - void invalidate() - { - _isValid = false; - } - SDFileEntry(const char *name) - { - strncpy(this->name, name, strlen(name) + 1); - _isValid = true; - } - - bool getName(char *name, int len) - { - if (!_isValid) - { - return false; - } - strncpy(name, this->name, len); - return true; - } - - bool isValid() { return _isValid; } -}; - -class SDFile -{ -private: - char base_path[1024]; - -#if defined(_WIN32) || defined(_WIN64) - WIN32_FIND_DATA ffd; - char szDir[MAX_PATH]; - HANDLE hFind = INVALID_HANDLE_VALUE; -#else - DIR *dir; - struct dirent *ent; -#endif - SDFileEntry currentEntry; - -public: - SDFile() - { - memset(base_path, 0, sizeof(base_path)); - } - ~SDFile() - { - close(); - } - bool open(const char *path); - SDFileEntry openNextFile(); - void rewindDirectory(); - void close(); - static bool exists(const char *path); - static bool remove(const char *path); -}; - const _TCHAR *create_sd_path(const char *path) { static _TCHAR file_path[8][_MAX_PATH]; @@ -329,803 +280,559 @@ bool f_match(char *f_name, char *c_name) return flg1; } -void thread_join(volatile PC80SD *p) +void addcmt(char *f_name, char *m_name) { -#if defined(_WIN32) || defined(_WIN64) - WaitForSingleObject((HANDLE)p->threadHandle, INFINITE); - CloseHandle((HANDLE)p->threadHandle); -#else - pthread_join(p->threadID, NULL); -#endif + unsigned int lp1 = 0; + while (f_name[lp1] != 0x00) + { + m_name[lp1] = f_name[lp1]; + lp1++; + } + if (f_name[lp1 - 4] != '.' || + (f_name[lp1 - 3] != 'C' && + f_name[lp1 - 3] != 'c') || + (f_name[lp1 - 2] != 'M' && + f_name[lp1 - 2] != 'm') || + (f_name[lp1 - 1] != 'T' && + f_name[lp1 - 1] != 't')) + { + m_name[lp1++] = '.'; + m_name[lp1++] = 'c'; + m_name[lp1++] = 'm'; + m_name[lp1++] = 't'; + } + m_name[lp1] = 0x00; } -void thread_yield() +PC80SD::~PC80SD() { - // Yield to other threads -#if defined(_WIN32) || defined(_WIN64) - SwitchToThread(); -#else - sched_yield(); -#endif + release(); } -void thread_sleep(int timer_count) +void PC80SD::initialize() { - // pthread_mutex_lock(&mtx); - current_pc80sd->write_signals_thread(-1, timer_count); - // printf("thread_sleep: start %d\n", timer_count); - // pthread_mutex_unlock(&mtx); - while(current_pc80sd->sleep_counter > 0 && !current_pc80sd->request_terminate) - { - // printf("thread_sleep: rest %d\n", current_pc80sd->sleep_counter); - thread_yield(); - // printf("thread_sleep: rest2 %d\n", current_pc80sd->sleep_counter); - } - // printf("thread_sleep: rest end %d\n", current_pc80sd->sleep_counter); - -//#if defined(_WIN32) || defined(_WIN64) -// // Windows̏ꍇ -// Sleep(milliseconds); // ̓~b -//#else -// // Linux/Mac̏ꍇ -// usleep(microseconds); // ̓}CNb -//#endif + strcpy(w_name, "default.dat"); + + // Ԃ̓eLg[(1.6MHz) + register_event(this, EVENT_TIMER, 0.625, true, ®ister_id); + + stateStack.clear(); } -uint8_t rcv4bit() +void PC80SD::release() { - printf("rcv4bit\n"); - if(current_pc80sd->request_terminate) - { - return 0; - } - - printf("rcv4bit: high wait\n"); - // HIGHɂȂ܂Ń[v - if(!(current_pc80sd->port[2].reg & 0x4)) - { - current_check = CHECK_HIGH; - } - // while ((current_pc80sd->port[2].reg & 0x4) == 0 && !current_pc80sd->request_terminate) - while (current_check != NOCHECK && !current_pc80sd->request_terminate) - { - // printf("rcv4bit: high wait\n"); - thread_yield(); - } - if (current_pc80sd->request_terminate) - { - return 0; - } +} - // M - uint8_t j_data = current_pc80sd->port[0].reg & 0xf; +void PC80SD::reset() +{ + release(); - printf("rcv4bit: low wait\n"); - // LOWɂȂ܂Ń[v - if((current_pc80sd->port[2].reg & 0x4)) - { - current_check = CHECK_LOW; - } - // FLGZbg - current_pc80sd->write_signals_thread(2, 0x80); - while (current_check != NOCHECK && !current_pc80sd->request_terminate) - { - // printf("rcv4bit: low wait\n"); - thread_yield(); - } - if (current_pc80sd->request_terminate) - { - return 0; - } + initialize(); +} - // FLGZbg - current_pc80sd->write_signals_thread(2, 0x00); +void PC80SD::write_signal(int id, uint32_t data, uint32_t mask) +{ + // printf("write signal(from Z80) %d %x %x\n", id, data, mask); + port[id].reg = (port[id].reg & ~mask) | (data & mask); +} - - // Ԍv̂߂Ɍ݂̎Ԃۑ - struct timespec start_time, end_time; - clock_gettime(CLOCK_MONOTONIC, &start_time); +void PC80SD::sendbytes(const uint8_t*data, int sz) +{ + stateStack.push(state); + stateStack.push(sub_state); + state = PC80SD_SNDBYTES; + sub_state = 0; + memcpy(send_datas, data, sz); + send_datas_count = sz; + send_datas_index = 0; +} - // rcv1byteꍇLOW̃`FbNZ80łȂ̂łȂɑ҂Ă - printf("receive end wait start\n"); - thread_sleep(16000); - printf("receive end wait end\n"); +void PC80SD::receivebytes(int count) +{ + stateStack.push(state); + stateStack.push(sub_state); + state = PC80SD_RCVBYTES; + sub_state = 0; + receive_datas_count = count; + receive_datas_index = 0; +} - clock_gettime(CLOCK_MONOTONIC, &end_time); - double elapsed = (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_nsec - start_time.tv_nsec) * 1e-9; - - printf("Elapsed time: %.9f seconds\n", elapsed); +void PC80SD::receive1byte() +{ + stateStack.push(state); + stateStack.push(sub_state); + state = PC80SD_RCV1BYTE; + sub_state = 0; + result_value = 0; +} - //printf("rcv4bit end\n"); - return (j_data); +void PC80SD::receive4bit() +{ + stateStack.push(state); + stateStack.push(sub_state); + state = PC80SD_RCV4BIT; + sub_state = 0; } -// 1BYTEM -void snd1byte(uint8_t i_data) +void PC80SD::popstate() { - //printf("snd1byte\n"); - if (current_pc80sd->request_terminate) - { - return; - } - // ʃrbg8rbgZbg - current_pc80sd->write_signals_thread(1, i_data); + sub_state = stateStack.top(); + stateStack.pop(); + state = stateStack.top(); + stateStack.pop(); +} - // HIGHɂȂ܂Ń[v - if(!(current_pc80sd->port[2].reg & 0x4)) - { - current_check = CHECK_HIGH; - } - // FLGPINHIGH - current_pc80sd->write_signals_thread(2, 0x80); +void PC80SD::proc_command() +{ +} - //printf("snd1byte high loop\n"); - while (current_check != NOCHECK && !current_pc80sd->request_terminate) - { - // printf("snd1byte: high wait\n"); - thread_yield(); - } - if (current_pc80sd->request_terminate) - { - return; - } +void PC80SD::send1byte(uint8_t data) +{ + stateStack.push(state); + stateStack.push(sub_state); + state = PC80SD_SND1BYTE; + sub_state = 0; + send_value = data; +} - // LOWɂȂ܂Ń[v - if((current_pc80sd->port[2].reg & 0x4)) - { - current_check = CHECK_LOW; - } - current_pc80sd->write_signals_thread(2, 0x00); +void PC80SD::loopend() +{ + state = PC80SD_INITIALIZE; + sub_state = 0; +} - printf("snd1byte low loop\n"); - //while ((current_pc80sd->port[2].reg & 0x4) != 0 && !current_pc80sd->request_terminate) - while (current_check != NOCHECK && !current_pc80sd->request_terminate) - { - // printf("snd1byte: low wait\n"); - thread_yield(); - } - if (current_pc80sd->request_terminate) - { - return; - } - printf("snd1byte end\n"); +void PC80SD::receivename(char *f_name) +{ + stateStack.push(state); + stateStack.push(sub_state); + state = PC80SD_RCVNAME; + sub_state = 0; + target_data = f_name; } -uint8_t rcv1byte() +void PC80SD::w_body(void) { - if(current_pc80sd->request_terminate) - { - return 0; - } - uint8_t i_data = 0; - i_data = rcv4bit() * 16; - i_data = i_data + rcv4bit(); - return i_data; + stateStack.push(state); + stateStack.push(sub_state); + state = PC80SD_WBODY; + sub_state = 0; } -// SD-CARDFILELIST -void dirlist() +void PC80SD::w_body_proc() { - printf("dirlist\n"); - // r擾 32+1܂ - for (unsigned int lp1 = 0; lp1 <= 32; lp1++) + switch(sub_state) { - c_name[lp1] = rcv1byte(); - } - printf("dirlist 2\n"); + case 0: + { + // wb_[ 0x3A + w_file->FputUint8(char(0x3A)); - SDFile file; - bool result = file.open(create_local_path(sd_folder_name)); - if (result) - { - // ԃR[hM(OK) - printf("send ok\n"); - snd1byte(0x00); - printf("send ok 2\n"); - - SDFileEntry entry = file.openNextFile(); - int cntl2 = 0; - unsigned int br_chk = 0; - int page = 1; - // So͂̏ꍇɂ16o͂Ƃňꎞ~AL[͂ɂpAł؂I - while (br_chk == 0) - { - if (entry.isValid()) - { - entry.getName(f_name, 36); - unsigned int lp1 = 0; - // ꌏM - // rŃt@Cl[/re擪10܂ŔrĈv̂o - if (f_match(f_name, c_name)) - { - while (lp1 <= 36 && f_name[lp1] != 0x00) - { - snd1byte(upper(f_name[lp1])); - lp1++; - } - snd1byte(0x0D); - snd1byte(0x00); - cntl2++; - } - } - if (!entry.isValid() || cntl2 > 15) - { - // pEł؂Iwv - snd1byte(0xfe); + sub_state++; + receivebytes(2); + break; + } + case 1: + { + // X^[gAhX擾A + s_adrs1 = receive_datas[0]; + s_adrs2 = receive_datas[1]; + w_file->FputUint8(s_adrs2); + w_file->FputUint8(s_adrs1); + // CHECK SUMvZA + csum = 0 - (s_adrs1 + s_adrs2); + w_file->FputUint8(csum); + // X^[gAhXZo + s_adrs = s_adrs1 + s_adrs2 * 256; - // IwM(0:p B:Oy[W ȊO:ł؂) - br_chk = rcv1byte(); - // Oy[W - if (br_chk == 0x42) - { - // 擪t@C - file.rewindDirectory(); - // entrylXV - entry = file.openNextFile(); - // x擪t@C - file.rewindDirectory(); - if (page <= 2) - { - // ݃y[W1y[W2y[WȂ1y[Wڂɖ߂鏈 - page = 0; - } - else - { - // ݃y[W3y[Wȍ~ȂOXy[W܂ł̃t@Cǂݔ΂ - page = page - 2; - cntl2 = 0; - while (cntl2 < page * 16) - { - entry = file.openNextFile(); - if (f_match(f_name, c_name)) - { - cntl2++; - } - } - } - br_chk = 0; - } - page++; - cntl2 = 0; - } - // t@C܂Ȃ玟ǂݍ݁AȂΑł؂w - if (entry.isValid()) - { - entry = file.openNextFile(); - } - else + sub_state++; + receivebytes(2); + break; + } + case 2: + { + // GhAhX擾 + s_adrs1 = receive_datas[0]; + s_adrs2 = receive_datas[1]; + // GhAhXZo + e_adrs = s_adrs1 + s_adrs2 * 256; + // t@CZoAubNZo + w_length = e_adrs - s_adrs + 1; + w_len1 = w_length / 255; + w_len2 = w_length % 255; + + sub_state++; + break; + } + case 3: + { + // f[^MA + // 0xFFubN + if(w_len1 == 0) { - br_chk = 1; + sub_state = 100; + break; } - // FDĽʂ18Ȃpwvɂ̂܂܏I - if (!entry.isValid() && cntl2 < 16 && page == 1) + w_file->FputUint8(char(0x3A)); + w_file->FputUint8(char(0xFF)); + csum = 0xff; + lp1 = 1; + sub_state++; + break; + } + case 4: + { + if(lp1 > 255) { + sub_state = 6; break; } + sub_state++; + receive1byte(); + break; } - // Iw - snd1byte(0xFF); - snd1byte(0x00); - } - else - { - snd1byte(0xf1); - } -} - -void addcmt(char *f_name, char *m_name) -{ - unsigned int lp1 = 0; - while (f_name[lp1] != 0x00) - { - m_name[lp1] = f_name[lp1]; - lp1++; - } - if (f_name[lp1 - 4] != '.' || - (f_name[lp1 - 3] != 'C' && - f_name[lp1 - 3] != 'c') || - (f_name[lp1 - 2] != 'M' && - f_name[lp1 - 2] != 'm') || - (f_name[lp1 - 1] != 'T' && - f_name[lp1 - 1] != 't')) - { - m_name[lp1++] = '.'; - m_name[lp1++] = 'c'; - m_name[lp1++] = 'm'; - m_name[lp1++] = 't'; - } - m_name[lp1] = 0x00; -} - -// r擾 32+1܂Ŏ擾A_uR[e[V͖ -void receive_name(char *f_name) -{ - char r_data; - unsigned int lp2 = 0; - for (unsigned int lp1 = 0; lp1 <= 32; lp1++) - { - r_data = rcv1byte(); - if (r_data != 0x22) + case 5: { - f_name[lp2] = r_data; - lp2++; + r_data = result_value; + w_file->FputUint8(r_data); + csum = csum + r_data; + lp1++; + sub_state = 4; + break; } - } -} - -// MONITOR LR}h .CMT LOAD -void cmt_load() -{ - bool flg = false; - // DOSt@C擾 - receive_name(m_name); - // t@C̎w肪邩 - if (m_name[0] != 0x00) - { - addcmt(m_name, f_name); - - // w肪ꍇ - // t@C݂ȂERROR - if (SDFile::exists(f_name) == true) + case 6: { - // t@CI[v - file = new FILEIO(); - if (file->Fopen(create_local_path("%s/%s", sd_folder_name, f_name), FILEIO_READ_BINARY)) + // CHECK SUMvZA + csum = 0 - csum; + w_file->FputUint8(csum); + w_len1--; + sub_state = 3; + break; + } + case 100: + { + // [ubN + if(w_len2 == 0) { - // f_lengthݒAr_count - f_length = file->FileLength(); - r_count = 0; - // ԃR[hM(OK) - snd1byte(0x00); - flg = true; + sub_state = 200; + break; } - else + w_file->FputUint8(char(0x3A)); + w_file->FputUint8(w_len2); + csum = w_len2; + lp1 = 1; + sub_state++; + break; + } + case 101: + { + if(lp1 > w_len2) { - snd1byte(0xf0); - flg = false; + sub_state = 103; + break; } + sub_state++; + receive1byte(); + break; } - else + case 102: { - snd1byte(0xf1); - flg = false; + r_data = result_value; + w_file->FputUint8(r_data); + csum = csum + r_data; + lp1++; + sub_state = 101; + break; } - } - else - { - // t@C̎w肪Ȃꍇ - // t@CGhɂȂĂȂ - if (f_length > r_count) + case 103: { - snd1byte(0x00); - flg = true; + // CHECK SUMvZA + csum = 0 - csum; + w_file->FputUint8(csum); + sub_state = 200; + break; } - else + case 200: { - snd1byte(0xf1); - flg = false; + w_file->FputUint8(char(0x3A)); + w_file->FputUint8(char(0x00)); + w_file->FputUint8(char(0x00)); + sub_state = 1000; + break; + } + case 1000: + { + popstate(); + break; } } +} - // ǂ΃t@CGh܂œǂݍ݂𑱍s - if (flg == true) +void PC80SD::cmt_save_proc() +{ + switch(sub_state) { - int rdata = 0; - - // wb_[oĂ܂œǂݔ΂ - while (rdata != 0x3a && rdata != 0xd3) + case 0: { - rdata = file->FgetUint8(); - r_count++; + sub_state++; + send1byte(0x00); + break; } - // wb_[M - snd1byte(rdata); - - // wb_[0x3aȂ瑱sAႦ΃G[ - if (rdata == 0x3a) + case 1: { - // START ADDRESS HI𑗐M - s_adrs1 = file->FgetUint8(); - r_count++; - snd1byte(s_adrs1); - - // START ADDRESS LO𑗐M - s_adrs2 = file->FgetUint8(); - r_count++; - snd1byte(s_adrs2); - s_adrs = s_adrs1 * 256 + s_adrs2; - - // CHECK SUM𑗐M - rdata = file->FgetUint8(); - r_count++; - snd1byte(rdata); - - // HEADER𑗐M - rdata = file->FgetUint8(); - r_count++; - snd1byte(rdata); + sub_state++; + receivename(m_name); + break; + } + case 2: + { + if(m_name[0] != 0x00) + { + addcmt(m_name, f_name); - // f[^𑗐M - b_length = file->FgetUint8(); - r_count++; - snd1byte(b_length); + if(w_file) + { + w_file->Fclose(); + } - // f[^0x00łȂԃ[v - while (b_length != 0x00) - { - for (unsigned int lp1 = 0; lp1 <= b_length; lp1++) + // t@C݂delete + if(SDFile::exists(f_name)) { - // f[^ǂݍőM - rdata = file->FgetUint8(); - r_count++; - snd1byte(rdata); + SDFile::remove(f_name); } - // CHECK SUM𑗐M - rdata = file->FgetUint8(); - r_count++; - snd1byte(rdata); - // f[^𑗐M - b_length = file->FgetUint8(); - r_count++; - snd1byte(b_length); - } - // f[^0x00̌㏈ - // CHECK SUM𑗐M - rdata = file->FgetUint8(); - r_count++; - snd1byte(rdata); - // t@CGhɒBĂFILE CLOSE - if (f_length == r_count) - { - file->Fclose(); - delete file; - file = nullptr; + // t@CI[v + w_file = new FILEIO(); + if (w_file->Fopen(create_sd_path(f_name), FILEIO_WRITE_BINARY)) + { + sub_state++; + send1byte(0x00); + break; + } else{ + sub_state = 1000; + send1byte(0xf0); + break; + } + } else { + sub_state = 1000; + send1byte(0xf6); + break; } + break; } - else - { - file->Fclose(); - delete file; - file = nullptr; - } - } -} - -// 5F9EH CMT 1Byteǂݍݏ̑ցAOPENĂt@C̑1Byteǂݍ݁AM -void cmt_5f9e(void) -{ - if (file == nullptr) - { - // JĂȂ - return; - } - int rdata = file->FgetUint8(); - r_count++; - snd1byte(rdata); - // t@CGh܂ŒBĂFILE CLOSE - if (f_length == r_count) - { - file->Fclose(); - delete file; - file = nullptr; - } -} - -void w_body(void) -{ - uint8_t r_data, csum; - // wb_[ 0x3A - w_file->FputUint8(char(0x3A)); - // X^[gAhX擾A - s_adrs1 = rcv1byte(); - s_adrs2 = rcv1byte(); - w_file->FputUint8(s_adrs2); - w_file->FputUint8(s_adrs1); - // CHECK SUMvZA - csum = 0 - (s_adrs1 + s_adrs2); - w_file->FputUint8(csum); - // X^[gAhXZo - s_adrs = s_adrs1 + s_adrs2 * 256; - // GhAhX擾 - s_adrs1 = rcv1byte(); - s_adrs2 = rcv1byte(); - // GhAhXZo - e_adrs = s_adrs1 + s_adrs2 * 256; - // t@CZoAubNZo - w_length = e_adrs - s_adrs + 1; - w_len1 = w_length / 255; - w_len2 = w_length % 255; - - // f[^MA - // 0xFFubN - while (w_len1 > 0) - { - w_file->FputUint8(char(0x3A)); - w_file->FputUint8(char(0xFF)); - csum = 0xff; - for (unsigned int lp1 = 1; lp1 <= 255; lp1++) - { - r_data = rcv1byte(); - w_file->FputUint8(r_data); - csum = csum + r_data; - } - // CHECK SUMvZA - csum = 0 - csum; - w_file->FputUint8(csum); - w_len1--; - } - - // [ubN - if (w_len2 > 0) - { - w_file->FputUint8(char(0x3A)); - w_file->FputUint8(w_len2); - csum = w_len2; - for (unsigned int lp1 = 1; lp1 <= w_len2; lp1++) - { - r_data = rcv1byte(); - w_file->FputUint8(r_data); - csum = csum + r_data; - } - // CHECK SUMvZA - csum = 0 - csum; - w_file->FputUint8(csum); - } - w_file->FputUint8(char(0x3A)); - w_file->FputUint8(char(0x00)); - w_file->FputUint8(char(0x00)); -} - -// MONITOR WR}h .CMT SAVE -void cmt_save(void) -{ - uint8_t r_data, csum; - // DOSt@C擾 - receive_name(m_name); - // t@C̎w肪΃G[ - if (m_name[0] != 0x00) - { - addcmt(m_name, f_name); - - if (w_file != nullptr) - { - w_file->Fclose(); - } - // t@C݂delete - if (SDFile::exists(f_name) == true) + case 3: { - SDFile::remove(f_name); + sub_state++; + w_body(); + break; } - // t@CI[v - w_file = new FILEIO(); - // SD.open( f_name, FILE_WRITE ); - if (w_file->Fopen(create_sd_path(f_name), FILEIO_WRITE_BINARY)) + case 4: { - // ԃR[hM(OK) - snd1byte(0x00); - w_body(); w_file->Fclose(); delete w_file; w_file = nullptr; + sub_state = 1000; + break; } - else + case 100: { - snd1byte(0xf0); + break; + } + + case 1000: + { + loopend(); + break; } - } - else - { - snd1byte(0xf6); } } -// BASICvOSAVE -void bas_save(void) +void PC80SD::cmt_load_proc() { - unsigned int lp1; - - // DOSt@C擾 - receive_name(m_name); - // t@C̎w肪΃G[ - if (m_name[0] != 0x00) + switch(sub_state) { - addcmt(m_name, f_name); - - if (w_file) + case 0: { - w_file->Fclose(); + sub_state=123; + send1byte(0x00); + break; } - // t@C݂delete - if (SDFile::exists(f_name) == true) + case 123: { - SDFile::remove(f_name); + flg = false; + sub_state=1; + receivename(m_name); + break; } - // t@CI[v - // w_file = SD.open( f_name, FILE_WRITE ); - w_file = new FILEIO(); - if (w_file->Fopen(create_sd_path(f_name), FILEIO_WRITE_BINARY)) + case 1: { - // ԃR[hM(OK) - snd1byte(0x00); - - // X^[gAhX擾 - s_adrs1 = rcv1byte(); - s_adrs2 = rcv1byte(); - // X^[gAhXZo - s_adrs = s_adrs1 + s_adrs2 * 256; - // GhAhX擾 - s_adrs1 = rcv1byte(); - s_adrs2 = rcv1byte(); - // GhAhXZo - e_adrs = s_adrs1 + s_adrs2 * 256; - // wb_[ 0xD3 x 9񏑂 - for (lp1 = 0; lp1 <= 9; lp1++) + if(m_name[0] != 0x00) { - w_file->FputUint8(char(0xD3)); + addcmt(m_name, f_name); + + // w肪ꍇ + // t@C݂ȂERROR + if (SDFile::exists(f_name) == true) + { + // t@CI[v + file = new FILEIO(); + if (file->Fopen(create_local_path("%s/%s", sd_folder_name, f_name), FILEIO_READ_BINARY)) + { + // f_lengthݒAr_count + f_length = file->FileLength(); + r_count = 0; + // ԃR[hM(OK) + flg = true; + sub_state++; + send1byte(0x00); + } + else + { + sub_state++; + send1byte(0xf0); + flg = false; + } + } + else + { + sub_state++; + send1byte(0xf1); + flg = false; + } + } else { + sub_state = 100; } - // DOSt@C̐擪6t@Cl[Ƃď - for (lp1 = 0; lp1 <= 5; lp1++) + break; + } + case 2: + { + if(flg == false) { - w_file->FputUint8(m_name[lp1]); + sub_state = 1000; + break; } - // f[^ (e_adrs - s_adrs +1)MA - for (lp1 = s_adrs; lp1 <= e_adrs; lp1++) + rdata = 0; + + // wb_[oĂ܂œǂݔ΂ + while (rdata != 0x3a && rdata != 0xd3) { - w_file->FputUint8(rcv1byte()); + rdata = file->FgetUint8(); + r_count++; } - // I 0x00 x 9񏑂 - for (lp1 = 1; lp1 <= 9; lp1++) + sub_state++; + send1byte(rdata); + break; + } + case 3: + { + // wb_[0x3aȂ瑱sAႦ΃G[ + if (rdata == 0x3a) { - w_file->FputUint8(char(0x00)); + // START ADDRESS HI𑗐M + s_adrs1 = file->FgetUint8(); + r_count++; + sub_state++; + send1byte(s_adrs1); + } else { + file->Fclose(); + delete file; + file = nullptr; + sub_state = 1000; + break; } - w_file->Fclose(); - delete w_file; - w_file = nullptr; + break; } - else + case 4: { - snd1byte(0xf0); + // START ADDRESS LO𑗐M + s_adrs2 = file->FgetUint8(); + r_count++; + sub_state++; + send1byte(s_adrs2); + s_adrs = s_adrs1 * 256 + s_adrs2; + break; } - } - else - { - snd1byte(0xf1); - } -} - -// BASICvOKILL -void bas_kill(void) -{ - unsigned int lp1; - - // DOSt@C擾 - receive_name(m_name); - // t@C̎w肪΃G[ - if (m_name[0] != 0x00) - { - addcmt(m_name, f_name); - - // ԃR[hM(OK) - snd1byte(0x00); - // t@C݂delete - if (SDFile::exists(f_name) == true) + case 5: { - SDFile::remove(f_name); - // ԃR[hM(OK) - snd1byte(0x00); + // CHECK SUM𑗐M + rdata = file->FgetUint8(); + r_count++; + sub_state++; + send1byte(rdata); + break; } - else + case 6: { - snd1byte(0xf1); + // HEADER𑗐M + rdata = file->FgetUint8(); + r_count++; + sub_state++; + send1byte(rdata); + break; } - } - else - { - snd1byte(0xf1); - } -} - -// BASICvOLOAD -void bas_load(void) -{ - bool flg = false; - // DOSt@C擾 - receive_name(m_name); - // t@C̎w肪邩 - if (m_name[0] != 0x00) - { - addcmt(m_name, f_name); - - // w肪ꍇ - // t@C݂ȂERROR - if (SDFile::exists(f_name) == true) + case 7: { - // t@CI[v - file = new FILEIO(); - // file = filSD.open( f_name, FILE_READ ); - // if( true == file ){ - if (file->Fopen(create_sd_path(f_name), FILEIO_READ_BINARY)) - { - // f_lengthݒAr_count - f_length = file->FileLength(); - r_count = 0; - // ԃR[hM(OK) - snd1byte(0x00); - flg = true; - } - else + // f[^𑗐M + b_length = file->FgetUint8(); + r_count++; + sub_state++; + send1byte(b_length); + break; + } + case 8: + { + // f[^0x00łȂԃ[v + if (b_length == 0x00) { - snd1byte(0xf0); - flg = false; + sub_state = 70; + break; } + lp1 = 0; + sub_state++; + break; } - else + case 9: { - snd1byte(0xf1); - flg = false; + if(lp1 > b_length) + { + sub_state = 10; + break; + } + rdata = file->FgetUint8(); + r_count++; + send1byte(rdata); + lp1++; + break; } - } - else - { - // t@C̎w肪Ȃꍇ - // t@CGhɂȂĂȂ - if (f_length > r_count) + case 10: { - snd1byte(0x00); - flg = true; + // CHECK SUM𑗐M + rdata = file->FgetUint8(); + r_count++; + sub_state++; + send1byte(rdata); + break; } - else + case 11: { - snd1byte(0xf1); - flg = false; + // f[^𑗐M + b_length = file->FgetUint8(); + r_count++; + sub_state=8; + send1byte(b_length); + break; } - } - // ǂ΃t@CGh܂œǂݍ݂𑱍s - if (flg == true) - { - int rdata = 0; - - // wb_[oĂ܂œǂݔ΂ - while (rdata != 0x3a && rdata != 0xd3) + case 70: { + // f[^0x00̌㏈ + // CHECK SUM𑗐M rdata = file->FgetUint8(); r_count++; + sub_state++; + send1byte(rdata); + break; } - // wb_[M - snd1byte(rdata); - // wb_[0xd3Ȃ瑱sAႦ΃G[ - if (rdata == 0xd3) + case 71: { - while (rdata == 0xd3) - { - rdata = file->FgetUint8(); - r_count++; - } - - // f[^M - int zcnt = 0; - int zdata = 1; - - snd1byte(rdata); - - // 0x0011‘܂œǂݍ݁AM - while (zcnt < 11) - { - rdata = file->FgetUint8(); - r_count++; - snd1byte(rdata); - if (rdata == 0x00) - { - zcnt++; - if (zdata != 0) - { - zcnt = 0; - } - } - zdata = rdata; - } - // t@CGhɒBĂFILE CLOSE if (f_length == r_count) { @@ -1133,424 +840,1172 @@ void bas_load(void) delete file; file = nullptr; } + sub_state = 1000; + break; + } + + case 100: + { + // t@C̎w肪Ȃꍇ + // t@CGhɂȂĂȂ + if (f_length > r_count) + { + sub_state++; + send1byte(0x00); + flg = true; + } + else + { + sub_state++; + send1byte(0xf1); + flg = false; + } + break; } - else + case 101: { - file->Fclose(); - delete file; - file = nullptr; + sub_state = 2; + break; } - } -} -// read file open -void sd_ropen(void) -{ - receive_name(f_name); - // t@C݂ȂERROR - if (SDFile::exists(f_name) == true) - { - // t@CI[v - // file = SD.open( f_name, FILE_READ ); - file = new FILEIO(); - if (file->Fopen(create_sd_path(f_name), FILEIO_READ_BINARY)) - { - // f_lengthݒAr_count - f_length = file->FileLength(); - r_count = 0; - // ԃR[hM(OK) - snd1byte(0x00); - } - else + case 1000: { - snd1byte(0xf0); + loopend(); + break; } } - else - { - snd1byte(0xf1); - } } -// write file append open -void sd_waopen(void) +void PC80SD::cmt_5f9e_proc() { - receive_name(w_name); - // t@CI[v - if (w_file != nullptr) - { - w_file->Fclose(); - } - // SD.open( w_name, FILE_WRITE ); - w_file = new FILEIO(); - if (w_file->Fopen(create_sd_path(w_name), FILEIO_WRITE_BINARY)) - { - // ԃR[hM(OK) - snd1byte(0x00); - } - else + switch(sub_state) { - snd1byte(0xf0); - } -} - -// write file new open -void sd_wnopen(void) -{ - receive_name(w_name); - if (w_file != nullptr) - { - w_file->Fclose(); - } - // t@C݂delete - if (SDFile::exists(w_name)) - { - SDFile::remove(w_name); - } - // t@CI[v - w_file = new FILEIO(); - if (w_file->Fopen(create_sd_path(w_name), FILEIO_WRITE_BINARY)) - { - // ԃR[hM(OK) - snd1byte(0x00); - } - else - { - snd1byte(0xf0); - } -} - -// 5ED9H -void sd_wdirect(void) -{ - if (w_file != nullptr) - { - w_body(); - w_file->Fclose(); - delete w_file; - w_file = nullptr; - // ԃR[hM(OK) - snd1byte(0x00); - } - else - { - snd1byte(0xf0); - } -} - -// write file close -void sd_wclose(void) -{ - w_file->Fclose(); - delete w_file; - w_file = nullptr; -} - -// write 1byte 5F2FH -void sd_w1byte(void) -{ - int rdata = rcv1byte(); - if (w_file != nullptr) - { - w_file->FputUint8(rdata); - // ԃR[hM(OK) - snd1byte(0x00); - } - else - { - snd1byte(0xf0); + case 0: + { + sub_state++; + send1byte(0x00); + break; + } + case 1: + { + if(file == nullptr) + { + sub_state = 1000; + break; + } + rdata = file->FgetUint8(); + r_count++; + sub_state++; + send1byte(rdata); + break; + } + case 2: + { + // t@CGh܂ŒBĂFILE CLOSE + if (f_length == r_count) + { + file->Fclose(); + delete file; + file = nullptr; + } + sub_state = 1000; + break; + } + case 1000: + { + loopend(); + break; + } } } -#ifdef _MSC_VER -unsigned __stdcall arduino_loop(void *lpx) -#else -void *arduino_loop(void *lpx) -#endif +void PC80SD::bas_load_proc() { - printf("arduino_loop start\n"); - volatile PC80SD *p = (PC80SD *)lpx; - - current_pc80sd = (PC80SD *)p; - - while (p->request_terminate == false) + switch(sub_state) { - ((PC80SD *)p)->write_signals_thread(1, 0); - ((PC80SD *)p)->write_signals_thread(2, 0); - thread_sleep(1000); - - printf("command wait...\n"); - uint8_t cmd = rcv1byte(); - printf("command received %d\n", (int)cmd); - if(p->request_terminate) + case 0: + { + sub_state++; + send1byte(0x00); + break; + } + case 1: { + flg = false; + sub_state++; + receivename(m_name); break; } + case 2: + { + if(m_name[0] != 0x00) + { + addcmt(m_name, f_name); - //// Serial.println(cmd,HEX); - if (eflg == false) + // w肪ꍇ + // t@C݂ȂERROR + if (SDFile::exists(f_name) == true) + { + // t@CI[v + file = new FILEIO(); + if (file->Fopen(create_local_path("%s/%s", sd_folder_name, f_name), FILEIO_READ_BINARY)) + { + // f_lengthݒAr_count + f_length = file->FileLength(); + r_count = 0; + // ԃR[hM(OK) + flg = true; + sub_state++; + send1byte(0x00); + } + else + { + sub_state++; + send1byte(0xf0); + flg = false; + } + } + else + { + sub_state++; + send1byte(0xf1); + flg = false; + } + } else { + sub_state = 100; + } + break; + } + case 3: { - switch (cmd) + if(flg == false) { - // 70h:PC-8001 CMTt@C SAVE - case 0x70: - //// Serial.println("CMT SAVE START"); - // ԃR[hM(OK) - snd1byte(0x00); - cmt_save(); - break; - // 71h:PC-8001 CMTt@C LOAD - case 0x71: - //// Serial.println("CMT LOAD START"); - // ԃR[hM(OK) - snd1byte(0x00); - cmt_load(); - break; - // 72h:PC-8001 5F9EH READ ONE BYTE FROM CMT - case 0x72: - //// Serial.println("CMT_5F9E START"); - // ԃR[hM(OK) - snd1byte(0x00); - cmt_5f9e(); - break; - // 73h:PC-8001 CMTt@C BASIC LOAD - case 0x73: - //// Serial.println("CMT BASIC LOAD START"); - // ԃR[hM(OK) - snd1byte(0x00); - bas_load(); - break; - // 74h:PC-8001 CMTt@C BASIC SAVE - case 0x74: - //// Serial.println("CMT BASIC SAVE START"); - // ԃR[hM(OK) - snd1byte(0x00); - bas_save(); - break; - // 75h:PC-8001 CMTt@C KILL - case 0x75: - //// Serial.println("CMT KILL START"); - // ԃR[hM(OK) - snd1byte(0x00); - bas_kill(); - break; - // 76h:PC-8001 SD FILE READ OPEN - case 0x76: - //// Serial.println("SD FILE READ OPEN START"); - // ԃR[hM(OK) - snd1byte(0x00); - sd_ropen(); - break; - // 77h:PC-8001 SD FILE WRITE APPEND OPEN - case 0x77: - //// Serial.println("SD FILE WRITE APPEND OPEN START"); - // ԃR[hM(OK) - snd1byte(0x00); - sd_waopen(); - break; - // 78h:PC-8001 SD FILE WRITE 1Byte - case 0x78: - //// Serial.println("SD FILE WRITE 1Byte START"); - // ԃR[hM(OK) - snd1byte(0x00); - sd_w1byte(); - break; - // 79h:PC-8001 SD FILE WRITE NEW OPEN - case 0x79: - //// Serial.println("SD FILE WRITE NEW OPEN START"); - // ԃR[hM(OK) - snd1byte(0x00); - sd_wnopen(); - break; - // 7Ah:PC-8001 SD WRITE 5ED9H - case 0x7A: - //// Serial.println("SD WRITE 5ED9H START"); - // ԃR[hM(OK) - snd1byte(0x00); - sd_wdirect(); - break; - // 7Bh:PC-8001 SD FILE WRITE CLOSE - case 0x7B: - //// Serial.println("SD FILE WRITE CLOSE START"); - // ԃR[hM(OK) - snd1byte(0x00); - sd_wclose(); + sub_state = 1000; break; + } + rdata = 0; - // 83hŃt@CXgo - case 0x83: - //// Serial.println("FILE LIST START"); - // ԃR[hM(OK) - printf("dirlist ok send start\n"); - snd1byte(0x00); - printf("dirlist ok send end\n"); - dirlist(); - break; - default: - // ԃR[hM(CMD ERROR) - snd1byte(0xF4); + // wb_[oĂ܂œǂݔ΂ + while (rdata != 0x3a && rdata != 0xd3) + { + rdata = file->FgetUint8(); + r_count++; } + sub_state++; + // wb_[M + send1byte(rdata); + break; } - else + case 4: { - // ԃR[hM(ERROR) - snd1byte(0xF0); - } - } - - printf("PC80SD thread end\n"); -#ifdef _MSC_VER - _endthreadex(0); - return 0; -#else - pthread_exit(NULL); - return NULL; -#endif -} - -PC80SD::~PC80SD() -{ - printf("PC80SD destructor\n"); - request_terminate = true; - thread_join(this); + // wb_[0xd3Ȃ瑱sAႦ΃G[ + if (rdata == 0xd3) + { + while (rdata == 0xd3) + { + rdata = file->FgetUint8(); + r_count++; + } - printf("PC80SD destructor end\n"); - release(); - printf("PC80SD destructor end 2\n"); -} + // f[^M + zcnt = 0; + zdata = 1; -void PC80SD::initialize() -{ - printf("PC80SD initialize\n"); -#if defined(_WIN32) || defined(_WIN64) - InitializeCriticalSection(&signal_cs); - threadHandle = _beginthreadex(NULL, 0, arduino_loop, this, 0, &threadID); -#else - pthread_mutex_init(&mtx, NULL); - pthread_create(&threadID, NULL, (void *(*)(void *)) & arduino_loop, this); -#endif - strcpy(w_name, "default.dat"); + sub_state++; + send1byte(rdata); + } else { + file->Fclose(); + delete file; + file = nullptr; + sub_state = 1000; + break; + } + break; + } + case 5: + { + // 0x0011‘܂œǂݍ݁AM + if(zcnt >= 11) + { + sub_state = 50; + break; + } - // Ԃ̓eLg[(1.6MHz) - register_event(this, EVENT_TIMER, 0.625, true, ®ister_id); + rdata = file->FgetUint8(); + r_count++; + sub_state++; + send1byte(rdata); + break; + } + case 6: + { + if (rdata == 0x00) + { + zcnt++; + if (zdata != 0) + { + zcnt = 0; + } + } + zdata = rdata; + sub_state = 5; + break; + } + case 50: + { + // t@CGhɒBĂFILE CLOSE + if (f_length == r_count) + { + file->Fclose(); + delete file; + file = nullptr; + } + sub_state = 1000; + break; + } - signalQueue.Clear(); - request_terminate = false; - sleep_counter = 0; -} + case 100: + { + // t@C̎w肪ȂV + // t@CGhɂȂĂȂ + if (f_length > r_count) + { + sub_state=3; + send1byte(0x00); + flg = true; + } + else + { + sub_state=3; + send1byte(0xf1); + flg = false; + } + break; + } -void PC80SD::release() -{ -#if defined(_WIN32) || defined(_WIN64) - DeleteCriticalSection(&signal_cs); -#else - pthread_mutex_destroy(&mtx); -#endif + case 1000: + { + loopend(); + break; + } + } } -void PC80SD::reset() +void PC80SD::bas_save_proc() { - printf("reset\n"); + switch(sub_state) + { + case 0: + { + sub_state++; + send1byte(0x00); + break; + } + case 1: + { + flg = false; + sub_state++; + receivename(m_name); + break; + } + case 2: + { + if(m_name[0] != 0x00) + { + addcmt(m_name, f_name); - request_terminate = true; - thread_join(this); + if(w_file) + { + w_file->Fclose(); + } - release(); + // t@C݂delete + if(SDFile::exists(f_name)) + { + SDFile::remove(f_name); + } - initialize(); - printf("initialize end\n"); -} + // t@CI[v + w_file = new FILEIO(); + if (w_file->Fopen(create_sd_path(f_name), FILEIO_WRITE_BINARY)) + { + sub_state++; + send1byte(0x00); + break; + } else{ + sub_state = 1000; + send1byte(0xf0); + break; + } + } else { + sub_state = 100; + } + break; + } + case 3: + { + sub_state++; + // X^[gAhX擾 + receivebytes(2); + break; + } + case 4: + { + s_adrs1 = receive_datas[0]; + s_adrs2 = receive_datas[1]; + // X^[gAhXZo + s_adrs = s_adrs1 + s_adrs2 * 256; -void PC80SD::write_signal(int id, uint32_t data, uint32_t mask) -{ - if(id == 2) - { - if(current_check == CHECK_HIGH) + sub_state++; + // GhAhX擾 + receivebytes(2); + break; + } + case 5: + { + s_adrs1 = receive_datas[0]; + s_adrs2 = receive_datas[1]; + // GhAhXZo + e_adrs = s_adrs1 + s_adrs2 * 256; + // wb_[ 0xD3 x 9񏑂 + for (lp1 = 0; lp1 <= 9; lp1++) + { + w_file->FputUint8(char(0xD3)); + } + // DOSt@C̐擪6t@Cl[Ƃď + for (lp1 = 0; lp1 <= 5; lp1++) + { + w_file->FputUint8(m_name[lp1]); + } + lp1 = s_adrs; + sub_state++; + break; + } + case 6: { - if(data != 0) + if(lp1 > e_adrs) { - current_check = NOCHECK; + sub_state = 8; + break; } - } else if(current_check == CHECK_LOW) + sub_state++; + receive1byte(); + break; + } + case 7: + { + w_file->FputUint8(result_value); + lp1++; + sub_state = 6; + break; + } + case 8: { - if(data == 0) + // I 0x00 x 9񏑂 + for (lp1 = 1; lp1 <= 9; lp1++) { - current_check = NOCHECK; + w_file->FputUint8(char(0x00)); } + w_file->Fclose(); + delete w_file; + w_file = nullptr; + sub_state = 1000; + break; + } + case 100: + { + sub_state = 1000; + send1byte(0xf1); + break; + } + + case 1000: + { + loopend(); + break; } } - printf("write signal(from Z80) %d %x %x\n", id, data, mask); - port[id].reg = (port[id].reg & ~mask) | (data & mask); } -void PC80SD::proc_signal() +void PC80SD::bas_kill_proc() { -#if defined(_WIN32) || defined(_WIN64) - EnterCriticalSection(&signal_cs); -#else - pthread_mutex_lock(&mtx); -#endif - // Queueɒ~ςꂽVOiCXbhŏ - bool queue_proc = false; - if(!signalQueue.IsEmpty()) + switch(sub_state) { - printf("Queue proc start ------------\n"); - queue_proc = true; + case 0: + { + sub_state++; + send1byte(0x00); + break; + } + case 1: + { + flg = false; + sub_state++; + receivename(m_name); + break; + } + case 2: + { + if(m_name[0] != 0x00) + { + addcmt(m_name, f_name); + + // ԃR[hM(OK) + sub_state++; + send1byte(0x00); + } else { + sub_state = 100; + } + break; + } + case 3: + { + // t@C݂delete + if(SDFile::exists(f_name)) + { + SDFile::remove(f_name); + sub_state = 1000; + send1byte(0x00); + break; + } else { + sub_state = 1000; + send1byte(0xf1); + break; + } + } + case 100: + { + sub_state = 1000; + send1byte(0xf1); + break; + } + case 1000: + { + loopend(); + break; + } } - while (!signalQueue.IsEmpty()) +} + +void PC80SD::sd_ropen_proc() +{ + switch(sub_state) { - SignalNode *node = signalQueue.Front(); - printf("signalQueue.Dequeue(to Z80) %d %d\n", node->ch, node->data); + case 0: + { + sub_state++; + send1byte(0x00); + break; + } + case 1: + { + flg = false; + sub_state++; + receivename(f_name); + break; + } + case 2: + { + // t@C݂ȂERROR + if (SDFile::exists(f_name) == true) + { + file = new FILEIO(); + if (file->Fopen(create_sd_path(f_name), FILEIO_READ_BINARY)) + { + // f_lengthݒAr_count + f_length = file->FileLength(); + r_count = 0; + // ԃR[hM(OK) + sub_state=1000; + send1byte(0x00); + break; + } else { + sub_state=1000; + send1byte(0xf0); + break; + } + } else { + sub_state=1000; + send1byte(0xf1); + break; + } + } + case 1000: + { + loopend(); + break; + } + } +} + +void PC80SD::sd_waopen_proc() +{ + switch(sub_state) + { + case 0: + { + sub_state++; + send1byte(0x00); + break; + } + case 1: + { + flg = false; + sub_state++; + receivename(m_name); + break; + } + case 2: + { + // t@CI[v + if (w_file != nullptr) + { + w_file->Fclose(); + } - write_signals(&port[node->ch].outputs, node->data); + w_file = new FILEIO(); + if (w_file->Fopen(create_sd_path(w_name), FILEIO_WRITE_BINARY)) + { + // AppendȂ̂łł̂ȁccH + w_file->Fseek(0, FILEIO_SEEK_END); - signalQueue.Dequeue(); + sub_state = 1000; + // ԃR[hM(OK) + send1byte(0x00); + } + else + { + sub_state = 1000; + send1byte(0xf0); + } + break; + } + case 1000: + { + loopend(); + break; + } } - if(queue_proc) +} + + +void PC80SD::sd_w1byte_proc() +{ + switch(sub_state) { - printf("Queue proc end ------------\n"); + case 0: + { + sub_state++; + send1byte(0x00); + break; + } + case 1: + { + sub_state++; + receive1byte(); + break; + } + case 2: + { + int rdata = result_value; + if (w_file != nullptr) + { + w_file->FputUint8(rdata); + sub_state = 1000; + // ԃR[hM(OK) + send1byte(0x00); + } + else + { + sub_state = 1000; + send1byte(0xf0); + } + break; + } + case 1000: + { + loopend(); + break; + } } +} - if(sleep_counter > 0) +void PC80SD::sd_wnopen_proc() +{ + switch(sub_state) { - sleep_counter--; - // printf("sleep dec %d\n", sleep_counter); + case 0: + { + sub_state++; + send1byte(0x00); + break; + } + case 1: + { + flg = false; + sub_state++; + receivename(m_name); + break; + } + case 2: + { + if (w_file != nullptr) + { + w_file->Fclose(); + } + + // t@C݂delete + if (SDFile::exists(w_name)) + { + SDFile::remove(w_name); + } + + // t@CI[v + w_file = new FILEIO(); + if (w_file->Fopen(create_sd_path(w_name), FILEIO_WRITE_BINARY)) + { + sub_state = 1000; + // ԃR[hM(OK) + send1byte(0x00); + } + else + { + sub_state = 1000; + send1byte(0xf0); + } + break; + } + case 1000: + { + loopend(); + break; + } } +} -#if defined(_WIN32) || defined(_WIN64) - LeaveCriticalSection(&signal_cs); -#else - pthread_mutex_unlock(&mtx); -#endif +// 5ED9H +void PC80SD::sd_wdirect_proc() +{ + switch(sub_state) + { + case 0: + { + sub_state++; + send1byte(0x00); + break; + } + case 1: + { + if (w_file != nullptr) + { + sub_state++; + w_body(); + } + else + { + sub_state = 1000; + send1byte(0xf0); + break; + } + break; + } + case 2: + { + w_file->Fclose(); + delete w_file; + w_file = nullptr; + // ԃR[hM(OK) + sub_state = 1000; + send1byte(0x00); + break; + } + case 1000: + { + loopend(); + break; + } + } } -void PC80SD::write_signals_thread(int id, uint32_t data) +// write file close +void PC80SD::sd_wclose_proc() { -#if defined(_WIN32) || defined(_WIN64) - EnterCriticalSection(&signal_cs); -#else - pthread_mutex_lock(&mtx); -#endif - if(id == -1) + switch(sub_state) { - sleep_counter = data; - // printf("sleep counter set %d\n", data); - } else { - // if(!signalQueue.IsEmpty()) - // { - // printf("write_signals_thread: has queue\n"); - // SignalNode *node = signalQueue.Front(); - // printf("write_signals_thread: front: %d : %d\n", node->ch, node->data); - // } - signalQueue.Enqueue(id, data); - printf("signalQueue.Enqueue(to Z80) %d %d\n", id, data); + case 0: + { + sub_state++; + send1byte(0x00); + break; + } + case 1: + { + w_file->Fclose(); + delete w_file; + w_file = nullptr; + sub_state = 1000; + break; + } + case 1000: + { + loopend(); + break; + } } +} -#if defined(_WIN32) || defined(_WIN64) - LeaveCriticalSection(&signal_cs); -#else - pthread_mutex_unlock(&mtx); -#endif +void PC80SD::dirlist_proc() +{ + switch(sub_state) + { + case 0: + { + sub_state++; + send1byte(0); + break; + } + case 1: + { + // 32+1M + sub_state++; + receivebytes(33); + + break; + } + case 2: + { + // OK + memcpy(c_name, receive_datas, 33); + sub_state++; + bool result = sd_file.open(create_local_path(sd_folder_name)); + if (result) + { + // OK + send1byte(0); + } else { + // error + send1byte(0xf1); + } + break; + } + case 3: + { + sd_entry = sd_file.openNextFile(); + cntl2 = 0; + br_chk = 0; + page = 1; + sub_state++; + } + case 4: + { + if(br_chk != 0) + { + sub_state = 10; + } else if (sd_entry.isValid()) + { + sd_entry.getName(f_name, 36); + unsigned int lp1 = 0; + // ꌏM + // rŃt@Cl[/re擪10܂ŔrĈv̂o + if (f_match(f_name, c_name)) + { + // ő36 or 0ɂȂ܂őM + int len = 36; + int slen = strlen(f_name); + len = min(len, slen); + sub_state++; + sendbytes((uint8_t*)f_name, len); + } + } + break; + } + case 5: + { + sub_state++; + sendbytes(cr_data, 2); + cntl2++; + break; + } + case 6: + { + if (!sd_entry.isValid() || cntl2 > 15) + { + // pEł؂Iwv + sub_state++; + send1byte(0xfe); + } else { + sub_state = 9; + } + break; + } + case 7: + { + sub_state++; + receive1byte(); + break; + } + case 8: + { + br_chk = result_value; + // Oy[W + if (br_chk == 0x42) + { + // 擪t@C + sd_file.rewindDirectory(); + // entrylXV + sd_entry = sd_file.openNextFile(); + // x擪t@C + sd_file.rewindDirectory(); + if (page <= 2) + { + // ݃y[W1y[W2y[WȂ1y[Wڂɖ߂鏈 + page = 0; + } + else + { + // ݃y[W3y[Wȍ~ȂOXy[W܂ł̃t@Cǂݔ΂ + page = page - 2; + cntl2 = 0; + while (cntl2 < page * 16) + { + sd_entry = sd_file.openNextFile(); + if (f_match(f_name, c_name)) + { + cntl2++; + } + } + } + br_chk = 0; + } + page++; + cntl2 = 0; + } + case 9: + { + // t@C܂Ȃ玟ǂݍ݁AȂΑł؂w + if (sd_entry.isValid()) + { + sd_entry = sd_file.openNextFile(); + } + else + { + br_chk = 1; + } + // FDĽʂ18Ȃpwvɂ̂܂܏I + if (!sd_entry.isValid() && cntl2 < 16 && page == 1) + { + sub_state++; + } else { + sub_state = 4; + } + break; + } + case 10: + { + sub_state++; + sendbytes(end_data, 2); + break; + } + case 11: + { + loopend(); + break; + } + } +} + +void PC80SD::proc_state() +{ + + switch(state) + { + case PC80SD_INITIALIZE: + { + write_signals(&port[1].outputs, 0); + // digitalWrite(FLGPIN,LOW); + write_signals(&port[2].outputs, port[2].reg & 0x7f); + state = PC80SD_WAIT_COMMAND; + sub_state = 0; + // break; + } + case PC80SD_WAIT_COMMAND: + { + switch(sub_state) + { + case 0: + sub_state++; + receive1byte(); + break; + case 1: + { + // result_value??R?}???h?l???????????(??????state?l?????g??) + state = result_value; + sub_state = 0; + break; + } + } + break; + } + case PC80SD_CMT_SAVE: + { + cmt_save_proc(); + break; + } + case PC80SD_CMT_LOAD: + { + cmt_load_proc(); + break; + } + case PC80SD_CMT_5F9E: + { + cmt_5f9e_proc(); + break; + } + case PC80SD_BAS_LOAD: + { + bas_load_proc(); + break; + } + case PC80SD_BAS_SAVE: + { + bas_save_proc(); + break; + } + case PC80SD_BAS_KILL: + { + bas_kill_proc(); + break; + } + case PC80SD_SD_ROPEN: + { + sd_ropen_proc(); + break; + } + case PC80SD_SD_WAOPEN: + { + sd_waopen_proc(); + break; + } + case PC80SD_SD_W1BYTE: + { + sd_w1byte_proc(); + break; + } + case PC80SD_SD_WNOPEN: + { + sd_wnopen_proc(); + break; + } + case PC80SD_SD_WDIRECT: + { + sd_wdirect_proc(); + break; + } + case PC80SD_SD_WCLOSE: + { + sd_wclose_proc(); + break; + } + case PC80SD_DIRLIST: + { + dirlist_proc(); + break; + } + case PC80SD_RCV1BYTE: + { + switch(sub_state) + { + case 0: + { + result_value = 0; + sub_state++; + receive4bit(); + break; + } + case 1: + { + result_value *= 16; + sub_state++; + receive4bit(); + break; + } + case 2: + { + popstate(); + break; + } + } + break; + } + case PC80SD_RCV4BIT: + { + switch(sub_state) + { + case 0: + { + if((port[2].reg & 0x4) == 0) + { + return; + } + sub_state = 1; + } + case 1: + { + result_value += port[0].reg & 0xf; + sub_state = 2; + break; + } + case 2: + { + write_signals(&port[2].outputs, 0x80 ); + sub_state = 3; + break; + } + case 3: + { + if((port[2].reg & 0x4) != 0) + { + return; + } + sub_state = 4; + break; + } + case 4: + { + write_signals(&port[2].outputs, 0x00); + wait_count = 0; + sub_state = 5; + break; + } + case 5: + { + wait_count++; + if(wait_count > 1000) + { + popstate(); + } + break; + } + } + break; + case PC80SD_SND1BYTE: + { + switch(sub_state) + { + case 0: + { + write_signals(&port[1].outputs, send_value); + + write_signals(&port[2].outputs, 0x80 ); + sub_state++; + break; + } + case 1: + { + if((port[2].reg & 0x4) == 0) + { + return; + } + + write_signals(&port[2].outputs, 0x00); + sub_state++; + break; + } + case 2: + { + if((port[2].reg & 0x4) != 0) + { + return; + } + popstate(); + break; + } + } + break; + } + case PC80SD_RCVBYTES: + { + if(receive_datas_count == 0) + { + popstate(); + return; + } + if(sub_state == 0) + { + sub_state++; + receive1byte(); + } + else + { + receive_datas[receive_datas_index] = result_value; + receive_datas_index++; + receive_datas_count--; + sub_state = 0; + } + break; + } + case PC80SD_SNDBYTES: + { + if(send_datas_count == 0) + { + popstate(); + return; + } + if(sub_state == 0) + { + sub_state++; + send1byte(send_datas[send_datas_index]); + } + else + { + send_datas_index++; + send_datas_count--; + sub_state = 0; + } + break; + } + case PC80SD_RCVNAME: + { + switch(sub_state) + { + case 0: + { + lp2 = 0; + sub_state++; + } + case 1: + { + sub_state++; + receive1byte(); + break; + } + case 2: + { + char r_data = result_value; + if(r_data != 0x22) + { + target_data[lp2] = r_data; + lp2++; + } + if(lp2 == 33) + { + popstate(); + break; + } else { + sub_state = 1; + } + break; + } + } + break; + } + case PC80SD_WBODY: + { + w_body_proc(); + break; + } + } + } } void PC80SD::event_callback(int event_id, int error) @@ -1558,7 +2013,7 @@ void PC80SD::event_callback(int event_id, int error) switch (event_id) { case EVENT_TIMER: - proc_signal(); + proc_state(); break; } } \ No newline at end of file diff --git a/gdemu/src/emulator/vm/pc80sd.h b/gdemu/src/emulator/vm/pc80sd.h index 0d75b6b..40e9b8d 100644 --- a/gdemu/src/emulator/vm/pc80sd.h +++ b/gdemu/src/emulator/vm/pc80sd.h @@ -14,84 +14,164 @@ #include "../emu.h" #include "device.h" +#if !(defined(_WIN32) || defined(_WIN64)) +#include +#include +#endif + #if !(defined(_WIN32) || defined(_WIN64)) #include #endif +class SDFileEntry +{ +private: + bool _isValid; + char name[1024]; -class SignalNode { public: - int ch; - uint32_t data; - SignalNode* next; + SDFileEntry() + { + invalidate(); + } + void invalidate() + { + _isValid = false; + } + SDFileEntry(const char *name) + { + strncpy(this->name, name, strlen(name) + 1); + _isValid = true; + } + + bool getName(char *name, int len) + { + if (!_isValid) + { + return false; + } + strncpy(name, this->name, len); + return true; + } + + bool isValid() { return _isValid; } }; -class SignalQueue { +class SDFile +{ private: - SignalNode* front; - SignalNode* rear; + char base_path[1024]; + +#if defined(_WIN32) || defined(_WIN64) + WIN32_FIND_DATA ffd; + char szDir[MAX_PATH]; + HANDLE hFind = INVALID_HANDLE_VALUE; +#else + DIR *dir; + struct dirent *ent; +#endif + SDFileEntry currentEntry; + +public: + SDFile() + { + memset(base_path, 0, sizeof(base_path)); + } + ~SDFile() + { + close(); + } + bool open(const char *path); + SDFileEntry openNextFile(); + void rewindDirectory(); + void close(); + static bool exists(const char *path); + static bool remove(const char *path); +}; +class StackNode { public: - SignalQueue() : front(nullptr), rear(nullptr) {} + int data; + StackNode* next; +}; - ~SignalQueue() { - while (front != nullptr) { - SignalNode* temp = front; - front = front->next; - delete temp; - } - } +class Stack { +private: + StackNode* top_node; +public: + Stack() : top_node(nullptr) {} - void Enqueue(int ch, uint32_t data) { - SignalNode* newNode = new SignalNode; - newNode->ch = ch; - newNode->data = data; - newNode->next = nullptr; - - if (rear == nullptr) { - front = rear = newNode; - } else { - rear->next = newNode; - rear = newNode; + ~Stack() { + while (!empty()) { + pop(); } } - void Dequeue() { - if (front == nullptr) - return; // Underflow case - - SignalNode* temp = front; - front = front->next; - - if (front == nullptr) - rear = nullptr; + void push(int value) { + StackNode* new_node = new StackNode(); + new_node->data = value; + new_node->next = top_node; + top_node = new_node; + } + void pop() { + if (empty()) { + // std::cerr << "Stack is empty, cannot pop a value\n"; + return; + } + StackNode* temp = top_node; + top_node = top_node->next; delete temp; } - SignalNode* Front() { - return front; + int top() const { + if (empty()) { + // std::cerr << "Stack is empty, cannot get top\n"; + return -1; + } + return top_node->data; } - void Clear() - { - while (front != nullptr) { - SignalNode* temp = front; - front = front->next; - delete temp; - } - rear = nullptr; + bool empty() const { + return top_node == nullptr; } - bool IsEmpty() { - return front == nullptr; + void clear() { + while (!empty()) { + pop(); + } } }; class PC80SD : public DEVICE { private: - void proc_signal(); + void proc_state(); + void proc_command(); + void sendbytes(const uint8_t*data, int sz); + void receivebytes(int count); + void receive1byte(); + void receive4bit(); + void popstate(); + void send1byte(uint8_t data); + void loopend(); + void receivename(char *f_name); + void w_body(); + void w_body_proc(); + + void dirlist_proc(); + void cmt_save_proc(); + void cmt_load_proc(); + void cmt_5f9e_proc(); + void bas_load_proc(); + void bas_save_proc(); + void bas_kill_proc(); + void sd_ropen_proc(); + void sd_waopen_proc(); + void sd_w1byte_proc(); + void sd_wnopen_proc(); + void sd_wdirect_proc(); + void sd_wclose_proc(); int state; int sub_state; @@ -105,9 +185,22 @@ class PC80SD : public DEVICE int receive_datas_count; int receive_datas_index; int wait_count; + char* target_data; Stack stateStack; + SDFile sd_file; + SDFileEntry sd_entry; + int cntl2; + unsigned int br_chk; + int page; + bool flg; + unsigned int lp1; + unsigned int lp2; + int rdata; + uint8_t r_data; + uint8_t csum; + int zcnt; + int zdata; public: - SignalQueue signalQueue; int register_id; struct { @@ -116,23 +209,13 @@ class PC80SD : public DEVICE outputs_t outputs; } port[3]; -#if defined(_WIN32) || defined(_WIN64) - unsigned threadID; - uintptr_t threadHandle; -#else - pthread_t threadID; -#endif - bool request_terminate; - int sleep_counter; - PC80SD(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu) { for(int i = 0; i < 3; i++) { initialize_output_signals(&port[i].outputs); port[i].reg = 0;//0xff; } - request_terminate = false; - sleep_counter = 0; + state = sub_state = 0; set_device_name(_T("PC8001(mk2)_SD")); } From 8c8b678a9b11c4ea40a8f2cad71cbd50e28aa773 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogino Date: Mon, 7 Aug 2023 18:36:51 +0900 Subject: [PATCH 5/9] =?UTF-8?q?=E3=83=AA=E3=82=BB=E3=83=83=E3=83=88?= =?UTF-8?q?=E3=81=A7PC8001mk2=5FSD=E3=81=8C=E3=83=AA=E3=82=BB=E3=83=83?= =?UTF-8?q?=E3=83=88=E3=81=95=E3=82=8C=E3=81=AA=E3=81=84=E5=95=8F=E9=A1=8C?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gdemu/src/emulator/vm/pc80sd.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/gdemu/src/emulator/vm/pc80sd.cpp b/gdemu/src/emulator/vm/pc80sd.cpp index 7cb8767..760786b 100644 --- a/gdemu/src/emulator/vm/pc80sd.cpp +++ b/gdemu/src/emulator/vm/pc80sd.cpp @@ -65,7 +65,7 @@ char w_name[40]; bool eflg = false; unsigned int s_adrs, e_adrs, w_length, w_len1, w_len2, s_adrs1, s_adrs2, b_length; -FILEIO *file, *w_file; +FILEIO *file = nullptr, *w_file = nullptr; const _TCHAR *create_sd_path(const char *path) { @@ -317,10 +317,22 @@ void PC80SD::initialize() register_event(this, EVENT_TIMER, 0.625, true, ®ister_id); stateStack.clear(); + state = PC80SD_INITIALIZE; + sub_state = 0; } void PC80SD::release() { + if(file) + { + file->Fclose(); + file = nullptr; + } + if(w_file) + { + w_file->Fclose(); + w_file = nullptr; + } } void PC80SD::reset() From 80bcd02452755f51773203105b1799eeae56ebac Mon Sep 17 00:00:00 2001 From: Hiroshi OGINO Date: Tue, 8 Aug 2023 14:12:50 +0900 Subject: [PATCH 6/9] =?UTF-8?q?=E3=83=AA=E3=82=BB=E3=83=83=E3=83=88?= =?UTF-8?q?=E5=87=A6=E7=90=86=E6=94=B9=E5=96=84=E3=80=81SD=E3=82=A2?= =?UTF-8?q?=E3=82=AF=E3=82=BB=E3=82=B9=E3=82=BF=E3=82=A4=E3=83=9F=E3=83=B3?= =?UTF-8?q?=E3=82=B0=E8=AA=BF=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gdemu/src/emulator/vm/pc80sd.cpp | 104 ++++++++++++++++++++++--------- 1 file changed, 76 insertions(+), 28 deletions(-) diff --git a/gdemu/src/emulator/vm/pc80sd.cpp b/gdemu/src/emulator/vm/pc80sd.cpp index 760786b..87f385a 100644 --- a/gdemu/src/emulator/vm/pc80sd.cpp +++ b/gdemu/src/emulator/vm/pc80sd.cpp @@ -239,7 +239,11 @@ bool SDFile::open(const char *path) void SDFile::close() { #if defined(_WIN32) || defined(_WIN64) - FindClose(hFind); + if(hFind != INVALID_HANDLE_VALUE) + { + FindClose(hFind); + hFind = INVALID_HANDLE_VALUE; + } #else if(dir != nullptr) { @@ -319,20 +323,27 @@ void PC80SD::initialize() stateStack.clear(); state = PC80SD_INITIALIZE; sub_state = 0; + memset(m_name, 0, sizeof(m_name)); + memset(f_name, 0, sizeof(f_name)); + memset(c_name, 0, sizeof(c_name)); + memset(new_name, 0, sizeof(new_name)); + memset(w_name, 0, sizeof(w_name)); + r_count = f_length = 0; } void PC80SD::release() { - if(file) - { - file->Fclose(); - file = nullptr; - } - if(w_file) + if (w_file) { w_file->Fclose(); w_file = nullptr; } + if (file) + { + file->Fclose(); + file = nullptr; + } + sd_file.close(); } void PC80SD::reset() @@ -1628,6 +1639,9 @@ void PC80SD::dirlist_proc() sub_state++; sendbytes((uint8_t*)f_name, len); } + else { + sub_state = 6; + } } break; } @@ -1733,12 +1747,32 @@ void PC80SD::proc_state() { case PC80SD_INITIALIZE: { - write_signals(&port[1].outputs, 0); - // digitalWrite(FLGPIN,LOW); - write_signals(&port[2].outputs, port[2].reg & 0x7f); - state = PC80SD_WAIT_COMMAND; - sub_state = 0; - // break; + switch (sub_state) + { + case 0: + { + write_signals(&port[1].outputs, 0); + sub_state++; + wait_count = 0; + // break; + } + case 1: + { + wait_count++; + if (wait_count > 1000) + { + sub_state++; + } + break; + } + case 2: + { + write_signals(&port[2].outputs, 0x00); + state = PC80SD_WAIT_COMMAND; + sub_state = 0; + } + } + break; } case PC80SD_WAIT_COMMAND: { @@ -1750,7 +1784,6 @@ void PC80SD::proc_state() break; case 1: { - // result_value??R?}???h?l???????????(??????state?l?????g??) state = result_value; sub_state = 0; break; @@ -1885,19 +1918,20 @@ void PC80SD::proc_state() case 4: { write_signals(&port[2].outputs, 0x00); - wait_count = 0; - sub_state = 5; - break; - } - case 5: - { - wait_count++; - if(wait_count > 1000) - { - popstate(); - } + popstate(); +// wait_count = 0; +// sub_state = 5; break; } +// case 5: +// { +// wait_count++; +// if(wait_count > 1000) +// { +// popstate(); +// } +// break; +// } } break; case PC80SD_SND1BYTE: @@ -1907,12 +1941,26 @@ void PC80SD::proc_state() case 0: { write_signals(&port[1].outputs, send_value); - - write_signals(&port[2].outputs, 0x80 ); + wait_count = 0; sub_state++; break; } case 1: + { + wait_count++; + if (wait_count > 700) + { + sub_state++; + } + break; + } + case 2: + { + write_signals(&port[2].outputs, 0x80 ); + sub_state++; + break; + } + case 3: { if((port[2].reg & 0x4) == 0) { @@ -1923,7 +1971,7 @@ void PC80SD::proc_state() sub_state++; break; } - case 2: + case 4: { if((port[2].reg & 0x4) != 0) { From 1c96253728d4994885d476f4d432c30bb1304c51 Mon Sep 17 00:00:00 2001 From: Hiroshi OGINO Date: Wed, 9 Aug 2023 00:02:42 +0900 Subject: [PATCH 7/9] =?UTF-8?q?PC-8001=5FSD=E5=AF=BE=E5=BF=9C(=E3=81=8A?= =?UTF-8?q?=E3=81=9D=E3=82=89=E3=81=8F)=E3=80=81=E8=A8=AD=E5=AE=9A?= =?UTF-8?q?=E3=81=AB=E3=82=88=E3=82=8BSD=E7=84=A1=E5=8A=B9=E5=8C=96?= =?UTF-8?q?=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * pc8001mk2.rcのSpecial Featuresの部分を下記のように書き換える事で、メニューからPC-8001mk2_SDの装着/非装着が可能となります(が、Godotではあまり関係ありません) POPUP "Special Features" BEGIN MENUITEM "M88 DiskDrv", ID_VM_DIPSWITCH8 MENUITEM "QUASIS88 Pesudo CMT", ID_VM_DIPSWITCH9 MENUITEM "PC-8001mk2_SD", ID_VM_DIPSWITCH11 END --- gdemu/src/emulator/vm/pc8801/pc88.cpp | 131 +++++++++++++++++++----- gdemu/src/emulator/vm/pc8801/pc88.h | 3 + gdemu/src/emulator/vm/pc8801/pc8801.cpp | 29 ++++-- gdemu/src/emulator/vm/pc8801/pc8801.h | 8 +- 4 files changed, 133 insertions(+), 38 deletions(-) diff --git a/gdemu/src/emulator/vm/pc8801/pc88.cpp b/gdemu/src/emulator/vm/pc8801/pc88.cpp index 8c1e52c..babde32 100644 --- a/gdemu/src/emulator/vm/pc8801/pc88.cpp +++ b/gdemu/src/emulator/vm/pc8801/pc88.cpp @@ -360,18 +360,23 @@ void PC88::initialize() #endif #if defined(SUPPORT_PC80_SDCARD) - if(fio->Fopen(create_local_path(_T("EXT_ROM_SHIFT_OFF.bin")), FILEIO_READ_BINARY)) { - fio->Fread(n80sdrom, 0x2000, 1); - fio->Fclose(); - } else if(fio->Fopen(create_local_path(_T("EXT_ROM_SHIFT_ON.bin")), FILEIO_READ_BINARY)) { - fio->Fread(n80sdrom, 0x2000, 1); - fio->Fclose(); - } else if(fio->Fopen(create_local_path(_T("EXT_ROM_A_OFF.bin")), FILEIO_READ_BINARY)) { - fio->Fread(n80sdrom, 0x2000, 1); - fio->Fclose(); - } else if(fio->Fopen(create_local_path(_T("EXT_ROM_A_ON.bin")), FILEIO_READ_BINARY)) { - fio->Fread(n80sdrom, 0x2000, 1); - fio->Fclose(); + if(config.dipswitch & DIPSWITCH_PC8001_SD) { + if(fio->Fopen(create_local_path(_T("EXT_ROM_SHIFT_OFF.bin")), FILEIO_READ_BINARY)) { + fio->Fread(n80sdrom, 0x2000, 1); + fio->Fclose(); + } else if(fio->Fopen(create_local_path(_T("EXT_ROM_SHIFT_ON.bin")), FILEIO_READ_BINARY)) { + fio->Fread(n80sdrom, 0x2000, 1); + fio->Fclose(); + } else if(fio->Fopen(create_local_path(_T("EXT_ROM_A_OFF.bin")), FILEIO_READ_BINARY)) { + fio->Fread(n80sdrom, 0x2000, 1); + fio->Fclose(); + } else if(fio->Fopen(create_local_path(_T("EXT_ROM_A_ON.bin")), FILEIO_READ_BINARY)) { + fio->Fread(n80sdrom, 0x2000, 1); + fio->Fclose(); + } else if(fio->Fopen(create_local_path(_T("EXT_ROM.bin")), FILEIO_READ_BINARY)) { + fio->Fread(n80sdrom, 0x2000, 1); + fio->Fclose(); + } } #endif @@ -641,7 +646,16 @@ void PC88::reset() update_tvram_memmap(); // XM8 version 1.10 #endif #endif - + +#if defined(_PC8001) +#ifdef SUPPORT_PC80_SDCARD + if (config.dipswitch & DIPSWITCH_PC8001_SD) { + memcpy(n80rom + 0x6000, n80sdrom, 0x2000); + } +#endif +#endif + + // misc usart_dcd = false; opn_busy = true; @@ -1295,18 +1309,46 @@ void PC88::write_io8(uint32_t addr, uint32_t data) break; #endif #ifdef SUPPORT_PC80_SDCARD - // for PC-8001mk2_SD + // for PC-8001mk2_SD +#if defined(_PC8001MK2) case 0x7c: // PPI_A - d_sdcard->write_io8(0, data); +#else + case 0xfc: // PPI_A +#endif + if(d_sdcard != NULL) + { + d_sdcard->write_io8(0, data); + } break; +#if defined(_PC8001MK2) case 0x7d: // PPI_B - d_sdcard->write_io8(1, data); +#else + case 0xfd: // PPI_B +#endif + if(d_sdcard != NULL) + { + d_sdcard->write_io8(1, data); + } break; +#if defined(_PC8001MK2) case 0x7e: // PPI_C - d_sdcard->write_io8(2, data); +#else + case 0xfe: // PPI_C +#endif + if(d_sdcard != NULL) + { + d_sdcard->write_io8(2, data); + } break; +#if defined(_PC8001MK2) case 0x7f: // PPI_R - d_sdcard->write_io8(3, data); +#else + case 0xff: // PPI_R +#endif + if(d_sdcard != NULL) + { + d_sdcard->write_io8(3, data); + } break; #endif #else @@ -1562,12 +1604,15 @@ void PC88::write_io8(uint32_t addr, uint32_t data) } break; #endif + +#if !(defined(SUPPORT_PC80_SDCARD) && defined(_PC8001)) case 0xfc: case 0xfd: case 0xfe: case 0xff: d_pio->write_io8(addr, data); break; +#endif } } @@ -1804,14 +1849,43 @@ uint32_t PC88::read_io8_debug(uint32_t addr) #ifdef SUPPORT_PC80_SDCARD // for PC-8001mk2_SD +#if defined(_PC8001MK2) case 0x7c: // PPI_A - return d_sdcard->read_io8(0); +#else + case 0xfc: // PPI_A +#endif + if(d_sdcard != NULL) + { + return d_sdcard->read_io8(0); + } +#if defined(_PC8001MK2) case 0x7d: // PPI_B - return d_sdcard->read_io8(1); +#else + case 0xfd: // PPI_B +#endif + if(d_sdcard != NULL) + { + return d_sdcard->read_io8(1); + } +#if defined(_PC8001MK2) case 0x7e: // PPI_C - return d_sdcard->read_io8(2); +#else + case 0xfe: // PPI_C +#endif + if(d_sdcard != NULL) + { + return d_sdcard->read_io8(2); + } +#if defined(_PC8001MK2) case 0x7f: // PPI_R - return d_sdcard->read_io8(3); +#else + case 0xff: // PPI_R +#endif + if(d_sdcard != NULL) + { + return d_sdcard->read_io8(3); + } + break; #endif @@ -1997,10 +2071,13 @@ uint32_t PC88::read_io8_debug(uint32_t addr) } break; #endif + +#if !(defined(SUPPORT_PC80_SDCARD) && defined(_PC8001)) case 0xfc: case 0xfd: case 0xfe: return d_pio->read_io8(addr); +#endif } return 0xff; } @@ -2294,12 +2371,14 @@ void PC88::update_n80_read() SET_BANK_R(0x6000, 0x7fff, n80erom); } else #endif - #ifdef SUPPORT_PC80_SDCARD - SET_BANK_R(0x6000, 0x7fff, n80sdrom); -#else - SET_BANK_R(0x6000, 0x7fff, rdmy); + if(config.dipswitch & DIPSWITCH_PC8001_SD) + { + SET_BANK_R(0x6000, 0x7fff, n80sdrom); + return; + } #endif + SET_BANK_R(0x6000, 0x7fff, rdmy); return; } #endif diff --git a/gdemu/src/emulator/vm/pc8801/pc88.h b/gdemu/src/emulator/vm/pc8801/pc88.h index 578bd48..ee8de46 100644 --- a/gdemu/src/emulator/vm/pc8801/pc88.h +++ b/gdemu/src/emulator/vm/pc8801/pc88.h @@ -428,6 +428,9 @@ class PC88 : public DEVICE set_device_name(_T("PC-8001 Core")); #else set_device_name(_T("PC-8801 Core")); +#endif +#ifdef SUPPORT_PC80_SDCARD + d_sdcard = NULL; #endif } ~PC88() {} diff --git a/gdemu/src/emulator/vm/pc8801/pc8801.cpp b/gdemu/src/emulator/vm/pc8801/pc8801.cpp index 949b582..e6cb05a 100644 --- a/gdemu/src/emulator/vm/pc8801/pc8801.cpp +++ b/gdemu/src/emulator/vm/pc8801/pc8801.cpp @@ -375,9 +375,14 @@ VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu) #endif #ifdef SUPPORT_PC80_SDCARD - pc80sd_pio = new I8255(this, emu); - pc80sd_pio->set_device_name(_T("8255 PIO (PC-8001(mkII)_SD board)")); - pc80sd_dev = new PC80SD(this, emu); + if(config.dipswitch & DIPSWITCH_PC8001_SD) { + pc80sd_pio = new I8255(this, emu); + pc80sd_pio->set_device_name(_T("8255 PIO (PC-8001(mkII)_SD board)")); + pc80sd_dev = new PC80SD(this, emu); + } else { + pc80sd_pio = NULL; + pc80sd_dev = NULL; + } #endif // set cpu device contexts @@ -507,13 +512,15 @@ VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu) } #endif #ifdef SUPPORT_PC80_SDCARD - pc88->set_context_sdcard(pc80sd_pio); - pc80sd_pio->clear_ports_by_cmdreg = true; - pc80sd_pio->set_context_port_a(pc80sd_dev, SIG_I8255_PORT_A, 0xFF, 0); - pc80sd_pio->set_context_port_c(pc80sd_dev, SIG_I8255_PORT_C, 0x0F, 0); + if(config.dipswitch & DIPSWITCH_PC8001_SD) { + pc88->set_context_sdcard(pc80sd_pio); + pc80sd_pio->clear_ports_by_cmdreg = true; + pc80sd_pio->set_context_port_a(pc80sd_dev, SIG_I8255_PORT_A, 0xFF, 0); + pc80sd_pio->set_context_port_c(pc80sd_dev, SIG_I8255_PORT_C, 0x0F, 0); - pc80sd_dev->set_context_port_b(pc80sd_pio, SIG_I8255_PORT_B, 0xFF, 0); - pc80sd_dev->set_context_port_c(pc80sd_pio, SIG_I8255_PORT_C, 0xF0, 0); + pc80sd_dev->set_context_port_b(pc80sd_pio, SIG_I8255_PORT_B, 0xFF, 0); + pc80sd_dev->set_context_port_c(pc80sd_pio, SIG_I8255_PORT_C, 0xF0, 0); + } #endif pc88cpu->set_context_mem(pc88); pc88cpu->set_context_io(pc88); @@ -698,7 +705,9 @@ void VM::reset() pc88pio->write_signal(SIG_I8255_PORT_C, 0, 0xff); #ifdef SUPPORT_PC80_SDCARD - pc80sd_pio->write_signal(SIG_I8255_PORT_C, 0, 0xff); + if(config.dipswitch & DIPSWITCH_PC8001_SD) { + pc80sd_pio->write_signal(SIG_I8255_PORT_C, 0, 0xff); + } #endif } diff --git a/gdemu/src/emulator/vm/pc8801/pc8801.h b/gdemu/src/emulator/vm/pc8801/pc8801.h index 80e2627..5aa0e7c 100644 --- a/gdemu/src/emulator/vm/pc8801/pc8801.h +++ b/gdemu/src/emulator/vm/pc8801/pc8801.h @@ -118,6 +118,7 @@ // #define SUPPORT_PC88_KANJI2 // #define SUPPORT_PC88_FDD_8INCH // #define SUPPORT_M88_DISKDRV + #define SUPPORT_PC80_SDCARD #endif #define SUPPORT_PC88_GSX8800 #define SUPPORT_PC88_PCG8100 @@ -166,7 +167,8 @@ #define DIPSWITCH_M88_DISKDRV 0x100 #define DIPSWITCH_QUASIS88_CMT 0x200 #define DIPSWITCH_16BIT 0x400 -#define DIPSWITCH_DEFAULT (DIPSWITCH_HMB20 + DIPSWITCH_GSX8800 + DIPSWITCH_PCG8100 + DIPSWITCH_CMDSING + DIPSWITCH_FDD_5INCH) +#define DIPSWITCH_PC8001_SD 0x800 +#define DIPSWITCH_DEFAULT (DIPSWITCH_HMB20 + DIPSWITCH_GSX8800 + DIPSWITCH_PCG8100 + DIPSWITCH_CMDSING + DIPSWITCH_FDD_5INCH + DIPSWITCH_PC8001_SD) #define USE_JOYSTICK_TYPE 2 #if defined(SUPPORT_PC88_FDD_8INCH) #define USE_FLOPPY_DISK 4 @@ -245,7 +247,9 @@ #else #define USE_PRINTER_TYPE 3 #endif -//#define USE_DEBUGGER +#if !defined(_GDNATIVE_) +#define USE_DEBUGGER +#endif #define USE_STATE #include "../../common.h" From 59e67d36f74cda81730a28d530999c1db7f87616 Mon Sep 17 00:00:00 2001 From: Hiroshi OGINO Date: Wed, 9 Aug 2023 22:57:48 +0900 Subject: [PATCH 8/9] =?UTF-8?q?1=E3=83=90=E3=82=A4=E3=83=88=E8=AA=AD?= =?UTF-8?q?=E3=81=BF=E8=BE=BC=E3=81=BF=E3=81=A7=E6=9C=80=E5=BE=8C=E3=81=BE?= =?UTF-8?q?=E3=81=A7=E8=AA=AD=E3=82=93=E3=81=A0=E5=A0=B4=E5=90=880xff?= =?UTF-8?q?=E3=81=8C=E8=BF=94=E3=82=8B=E3=82=88=E3=81=86=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gdemu/src/emulator/vm/pc80sd.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gdemu/src/emulator/vm/pc80sd.cpp b/gdemu/src/emulator/vm/pc80sd.cpp index 87f385a..5570fe4 100644 --- a/gdemu/src/emulator/vm/pc80sd.cpp +++ b/gdemu/src/emulator/vm/pc80sd.cpp @@ -913,7 +913,9 @@ void PC80SD::cmt_5f9e_proc() { if(file == nullptr) { - sub_state = 1000; + // t@C܂ōsĂ邩JĂȂꍇ0xffԂ + sub_state++; + send1byte(0xff); break; } rdata = file->FgetUint8(); @@ -925,7 +927,7 @@ void PC80SD::cmt_5f9e_proc() case 2: { // t@CGh܂ŒBĂFILE CLOSE - if (f_length == r_count) + if (f_length == r_count && file != nullptr) { file->Fclose(); delete file; From f61581db6d07217e2d23413a0deb049271c99a6d Mon Sep 17 00:00:00 2001 From: Hiroshi OGINO Date: Fri, 11 Aug 2023 16:45:02 +0900 Subject: [PATCH 9/9] =?UTF-8?q?SD=E3=81=AE=E3=83=95=E3=82=A1=E3=82=A4?= =?UTF-8?q?=E3=83=AB=E4=B8=80=E8=A6=A7=E3=81=A7=E3=83=9A=E3=83=BC=E3=82=B8?= =?UTF-8?q?=E3=82=92=E3=81=BE=E3=81=9F=E3=81=90=E5=A0=B4=E5=90=88=E3=81=AB?= =?UTF-8?q?=E6=AD=A3=E3=81=97=E3=81=8F=E5=8B=95=E3=81=8B=E3=81=AA=E3=81=84?= =?UTF-8?q?=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gdemu/src/emulator/vm/pc80sd.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gdemu/src/emulator/vm/pc80sd.cpp b/gdemu/src/emulator/vm/pc80sd.cpp index 5570fe4..4c87355 100644 --- a/gdemu/src/emulator/vm/pc80sd.cpp +++ b/gdemu/src/emulator/vm/pc80sd.cpp @@ -1609,6 +1609,7 @@ void PC80SD::dirlist_proc() send1byte(0); } else { // error + sub_state = 11; send1byte(0xf1); } break; @@ -1626,6 +1627,7 @@ void PC80SD::dirlist_proc() if(br_chk != 0) { sub_state = 10; + break; } else if (sd_entry.isValid()) { sd_entry.getName(f_name, 36); @@ -1640,11 +1642,14 @@ void PC80SD::dirlist_proc() len = min(len, slen); sub_state++; sendbytes((uint8_t*)f_name, len); + break; } else { sub_state = 6; + break; } } + sub_state = 6; break; } case 5: @@ -1674,6 +1679,7 @@ void PC80SD::dirlist_proc() } case 8: { + sub_state++; br_chk = result_value; // Oy[W if (br_chk == 0x42)