Автор Тема: Доработка Burn2Slot  (Прочитано 737 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Talking_Sword

  • Пользователь
  • Сообщений: 903
  • Happy Games Only!
    • Просмотр профиля
Доработка Burn2Slot
« : 17 Ноябрь 2023, 13:50:19 »
У меня снова вопрос с некоторым уклоном в железо (скорее всего).

Покупал на Aliexpress картриджи под перепрошивку, но на этот раз попалась на них микросхема LH28F800BJE, а ее не поддерживает ни Burn2Slot, ни GBABF-SHN. Тут наверно я сам себе злобный Буратино, так как взял игру на 512 КБ, подумал, что большой объем для тех игр, которые хотел записать не нужен. Наверно, если бы взял что-то на 2 МБ, то могла бы попасться и какая-нибудь поддерживаемая микросхема.

Тем не менее, хочу попробовать дописать в Burn2Slot поддержку данной микросхемы.

Вопросы: вот Datasheet на микросхему. На странице 21 есть алгоритм в виде блок-схемы для прошивки одного слова\байта. На блок-схеме есть SR.7=, я так понимаю, это проверка Status Register, о котором написано на странице 18. Я так понимаю, нужно проверять бит 7. Для этого нужно считать информацию. Но там будет сразу считываться по 8, а может по 16 бит (не уверен, но шина 16-битная), и отображаться как шестнадцетиричное число.

А как в Си (Burn2Slot ведь на Си написан?) "посмотреть" отдельный бит?
« Последнее редактирование: 26 Ноябрь 2023, 06:22:26 от Talking_Sword »

Оффлайн Yoti

  • Пользователь
  • Сообщений: 4452
  • Пол: Мужской
  • Не тро-гай ме-ня
    • Steam
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #1 : 17 Ноябрь 2023, 13:54:48 »
А как в Си (Burn2Slot ведь на Си написан?) "посмотреть" отдельный бит?
Есть битовый сдвиг, есть маска.

Оффлайн Talking_Sword

  • Пользователь
  • Сообщений: 903
  • Happy Games Only!
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #2 : 17 Ноябрь 2023, 15:29:36 »
Yoti, честно говоря, не слишком понятно. У меня с программированием не очень хорошо.

Можно ссылки на какие-нибудь статьи\уроки, где бы это понятно объяснялось? Желательно с примерами кода

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 5051
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #3 : 17 Ноябрь 2023, 15:38:10 »
"посмотреть" отдельный бит?
Если num - числовой тип и используется в условии if, то варианты:
if ((num & 0x80) == 0x80) {
// 7-й бит установлен
}
if (!!(num & 0x80)) {} // В JS стиле
if (!(num & 0x80)) {} // 7-й бит не установлен
if (num & 0x80) {} // Нехорошо, неявное преобразование
UPD: Поправил комменты. Побаловаться с кодом можно: https://www.onlinegdb.com/online_c++_compiler.

Оффлайн Talking_Sword

  • Пользователь
  • Сообщений: 903
  • Happy Games Only!
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #4 : 17 Ноябрь 2023, 18:12:55 »
Sharpnull, огромное спасибо, что бы я без вас делал! :thumbup:

И еще, "бесполезный" вопрос из разряда "просто интересно": num & 0x80 - это выглядит как логическая операция "И". Не совсем понял, а как это помогает "понять", установлен у нас 7-ой бит или нет?

По крайней мере, мне понятно, что 0x80 - это 10000000 в двоичной системе, то есть установленный 7-ой бит. А вот "if (!(num & 0x80)", по идее, чтобы условие if выполнялось, нужно, чтобы в скобках было true. А как "num & 0x80" дает true, если в num 7-ой бит будет равен "1"?

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 5051
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #5 : 17 Ноябрь 2023, 18:37:28 »
num & 0x80 - это выглядит как логическая операция "И"
Это побитовая (битовая) операция "И", значит действия между соответствующими битами чисел. Логическое "И" записывается как &&.
А вот "if (!(num & 0x80)", по идее, чтобы условие if выполнялось, нужно, чтобы в скобках было true. А как "num & 0x80" дает true, если в num 7-ой бит будет равен "1"?
В C ненулевое значение - "истина" и не было изначально true, false и bool. Поэтому if (!0x80) и if (!1) не выполняется всегда, а if (!0) выполняется всегда. Можно даже написать бесконечный цикл как while ("inf") {}. Замечу, "if (!(num & 0x80))" - условие выполняется, если 7-й бит не установлен.
Про if (num & 0x80) ошибся, думал было предупреждение (проверил, его нет в Visual Studio и GCC), с чем-то перепутал.

Оффлайн Talking_Sword

  • Пользователь
  • Сообщений: 903
  • Happy Games Only!
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #6 : 17 Ноябрь 2023, 20:09:25 »
В C ненулевое значение - "истина" и не было изначально true, false и bool. Поэтому if (!0x80) и if (!1) не выполняется всегда, а if (!0) выполняется всегда.
Спасибо, понятно.

Родил вот такой код на основе того, что посоветовал Sharpnull:

void eraseSharp()
{
printTop("Chip Erase...");
write_word()(0x0, 0x70);
while(!(read_word()(0x0) & 0x80){
wait();
}
write_word()(0x0, 0x30);
write_word()(0x0, 0xD0);
while(!(read_word()(0x0) & 0x80){
wait();
}
printTop("Done.\n\n");
}

Оффлайн Марат

  • Пользователь
  • Сообщений: 556
  • Пол: Мужской
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #7 : 17 Ноябрь 2023, 20:24:53 »
И что этот код работает?
Пустые скобки после write_word выглядят странными. Также странно выглядит чтение read_word. В моём понимании должно быть так write_word(0x0, 0x70);
read_word() без всяких аргументов.

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 5051
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #8 : 17 Ноябрь 2023, 20:30:04 »
Пустые скобки после write_word выглядят странными.
Функция возвращает функцию: https://github.com/vrodin/Burn2Slot/blob/master/arm9/source/app.cpp. UPD: Можно было бы сделать макрос или функцию обёртку, чтобы выглядело "нормально".

Оффлайн Talking_Sword

  • Пользователь
  • Сообщений: 903
  • Happy Games Only!
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #9 : 17 Ноябрь 2023, 20:36:55 »
И что этот код работает?
Да, только что стер микросхему. Уря! :jumpy: Только забыл добавить "\n" после "Chip Erase...".

Теперь осталось только написать код прошивки (опираясь на исходный код Burn2Slot).

Добавлено позже:
Сделал код для прошивки:

void writeWord22XX(u32 addr, u16 data)
{
write_word()(0x0, 0x70);
int timeout = 0x20000;
while(timeout && !(read_word()(0x0) & 0x80)){
timeout--;
wait();
}
write_word()(0x0, 0x40);
write_word_rom(addr, data);
timeout = 0x20000;
while(timeout && !(read_word()(0x0) & 0x80)){
timeout--;
wait();
}
}

И да, он работает. Заработало с первого раза! Даже сам не ожидал, что так легко получится.

Только сразу говорю, название функции "writeWord22XX", мягко так скажем, не соответствует действительности. Никакие "22XX" он прошить не сможет. Просто я хотел максимально упростить себе задачу, поэтому, просто заменил функцию "writeWord22XX" своей, чтобы не приходилось определять тип микросхемы, а затем выбирать на основе этого "правильную" функцию. Поддержка "нормальных" микросхем в моей модифицированной версии сломана, теперь она может прошивать только Sharp. Но я и не ставил цели сделать универсальную программу, цель была решить свою задачу, и реализация, как говорят по Английски "quick and dirty".

Но в будущем надо все-таки сделать отдельную функцию, и сделать определение типа микросхемы, чтобы выбрать правильную функцию.

P.S.: а вот перед тем, как стирать решил сравнить данные между двумя картриджами, так как покупал два одинаковых картриджа, данные в них должны совпадать. Делал это потому, что в теории, могут прислать картридж с битой памятью. Если данные в них не совпадут, значит один из них битый. И данные не совпали - один совпадал с No-Intro, у другого были расхождения в нескольких местах, ну и "родная" игра глючила как на приставке, так и на эмуляторе. Но при этом, когда перезаписал "плохой" картридж, то данные в него записались правильно, байт-в-байт. Странно, почему тогда "родная" игра была криво записана? Единственное, что могу предположить что может Flash-память какая-то "уставшая" и помнит данные только когда они недавно записаны, а потом "забывает".
« Последнее редактирование: 17 Ноябрь 2023, 23:15:53 от Talking_Sword »

Оффлайн perfect_genius

  • Пользователь
  • Сообщений: 1159
    • ВКонтакте
    • Steam
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #10 : 19 Ноябрь 2023, 00:38:18 »
Попробуй 0b10000000 вместо 0x80, вдруг твой компилятор поддерживает. Такое появилось в Си23, но было и до него в некоторых компиляторах.
(И, пожалуйста, не пиши национальности и названия языков с большой буквы. Не тащи в русский гадости из английского :))

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 5051
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #11 : 19 Ноябрь 2023, 02:13:58 »
Такое появилось в Си23, но было и до него в некоторых компиляторах.
У него C++, а там двоичные литералы с C++14. Я всё равно пишу в hex, двоичная запись занимает больше места. С разделителем пойдёт - 0b1000'0000.

Оффлайн Talking_Sword

  • Пользователь
  • Сообщений: 903
  • Happy Games Only!
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #12 : 19 Ноябрь 2023, 12:39:29 »
Си23
Цифра, я так понимаю год? Что-то совсем новое. Я больше тяготею к старым стандартам. В любом случае, так, как написал Sharpnull работает, а это самое главное.

Только единственное, что я сказал уже ранее, что надо бы еще сделать так, чтобы программа могла перезаписывать как и "22XX" так и Sharp. А то я сейчас заменил код для "обычных" микросхем, и их программа прошивать "разучилась".

Но похоже у меня это не получится сделать, так как для проверки кода нужна микросхема, на которой он будет проверяться, а я уже оба своих картриджа прошил нужными мне играми, и больше прошивать их не хочу.
Не тащи в русский гадости из английского :)
?
« Последнее редактирование: 19 Ноябрь 2023, 12:46:31 от Talking_Sword »

Оффлайн perfect_genius

  • Пользователь
  • Сообщений: 1159
    • ВКонтакте
    • Steam
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #13 : 20 Ноябрь 2023, 19:25:40 »
Я больше тяготею к старым стандартам.
Тебе надо просто проверить, необязательно следовать каким-то стандартам, оно обратно совместимо, да и не совсем новый стандарт - в С++ появилось давно.
Цифра 1 в 0b10000000 - это твой седьмой бит. Так удобнее манипулировать отдельными битами вручную, чем лезть в калькулятор за 0x80.
0x40 вон шестой бит - 0b01000000.

?
Цитата
как говорят по Английски
из-за ломанного Английского
на оригинальной Японской
сплошь в Японском
играх на Японской
по Русски
картриджи с Русскими версиями



Оффлайн wolfer

  • Пользователь
  • Сообщений: 1664
  • Пол: Мужской
  • Mens sana in corpore sano
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #14 : 20 Ноябрь 2023, 19:59:48 »
Проще функцию написать для универсальности, возвращающую 1 или 0, isBit(UINT number, int Count) какую-нибудь, с побитовым сдвигом вправо и & 1  в конце...

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 5051
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #15 : 20 Ноябрь 2023, 22:04:07 »
Проще функцию написать для универсальности
Нет, это и так просто (a & 0x80) и можно написать #define FLAG 0x0100 и (a & FLAG). Для C++ уже std::bitset, если хочется абстракций.

Оффлайн wolfer

  • Пользователь
  • Сообщений: 1664
  • Пол: Мужской
  • Mens sana in corpore sano
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #16 : 20 Ноябрь 2023, 22:08:02 »
Не люблю плюсы, с89 достаточен для любых вычислительных или низкоуровневых задач. А у плюсов стандарт скачет и раздувается, я уже на последнем в код не втыкаю…

Оффлайн MetalliC

  • Технический консультант
  • Сообщений: 9386
  • Пол: Мужской
  • Demul team / MAME developer
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #17 : 21 Ноябрь 2023, 01:58:15 »
с89 достаточен для любых вычислительных или низкоуровневых задач
достаточен, но как говорится, у С++ всё же есть пара плюсов :)
хотя бы те же темплейты (шаблоны), и да, приблизительно то же можно сделать на С с кучкой макросов, но спустя недельку сам нихрена не сможешь разобраться в куче своих же навороченых #define конструкций

Оффлайн wolfer

  • Пользователь
  • Сообщений: 1664
  • Пол: Мужской
  • Mens sana in corpore sano
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #18 : 21 Ноябрь 2023, 07:06:02 »
достаточен, но как говорится, у С++ всё же есть пара плюсов :)
хотя бы те же темплейты (шаблоны), и да, приблизительно то же можно сделать на С с кучкой макросов, но спустя недельку сам нихрена не сможешь разобраться в куче своих же навороченых #define конструкций
Естественно, для разработки больших проектов лучше сразу использовать плюсы. Я же не говорю, что у ник нет преимуществ, просто не люблю)) Так как во времена своей молодости мог позволить себе писать код в С стиле… А сейчас ностальгирую, как по сеге :D

Оффлайн Talking_Sword

  • Пользователь
  • Сообщений: 903
  • Happy Games Only!
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #19 : 22 Ноябрь 2023, 21:52:29 »
Продолжаю дорабатывать код Burn2Slot. Как говорил в прошлый раз, тогда заменил "родную" функцию для прошивки слова своей, так как хотел максимально упростить себе задачу. Но из-за этого программа "разучивается" работать с "обычными" микросхемами. Изначально думал, что потом постараюсь сделать так, чтобы программа смогла работать с любым типом микросхем, то есть не заменять, а добавить свою функцию к уже имеющимся в программе. Но не хотелось эксперементировать на своих картриджах, так как каждый цикл стирание\запись может стать для микросхемы последним, а для тестирования кода это нужно. Но решил все-таки рискнуть.

Код пока не запускал, есть вопросы.

Решил переделать с if-else на switch, так как теперь нужен выбор из трех вариантов:

void erase(u32 needSpace)
{
for(int addr = 0; addr < needSpace; addr += 0x8000) {
switch(chipType) {
case 0:
eraseSector22XX(addr);
break;
case 1:
for(int smallAddr = addr; smallAddr < addr + 0x8000; smallAddr += 0x2000)
eraseSectorIntel(smallAddr);
break;
case 2:
eraseSharp();
return;
break;
default:
return;
}
printTop("\rERASE %d\%", (addr + 0x8000) * 100/needSpace );
}
printTop("\n");
}

Но суть в том, что в программе используется не полное, а "частичное" стирание, программа "расчищает" секторы под объем записываемого файла, остальные не трогает. Поэтому используется цикл, который выполняется столько раз, сколько секторов нужно стереть для записи файла. Но мне же было лень реализовывать посекторное стирание, поэтому в функции eraseSharp сделал Chip Erase - полное стирание, это удобно тем, что дал один раз комманду, а потом просто ждешь, когда микросхема сама себя сотрет. Но данную функцию нужно вызывать только один раз за прошивку.

Правильно ли я понимаю, что return; после вызова функции eraseSharp досрочно завершит цикл и прервет выполнение функции erase?

Также, прочитал здесь, что если не написать break;, то сразу начнут выполняться следующие операторы. Правильно ли я понимаю, что из case 2 можно смело убрать return; и break;, и после этого начнет выполняться default, в котором есть нужный нам return;?
« Последнее редактирование: 22 Ноябрь 2023, 21:59:02 от Talking_Sword »

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 5051
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #20 : 22 Ноябрь 2023, 22:06:19 »
Talking_Sword, да, да. Но я бы в case 2 оставил только return, а в default перед return вывод ошибки, что нет такого типа.
UPD: Лучше не использовать "проваливание", break/return забывают случайно и компилятор может жаловаться, для этого даже сделали [[fallthrough]] в C++17, чтобы сказать компилятору о намерениях (https://en.cppreference.com/w/cpp/language/attributes/fallthrough).

Оффлайн wolfer

  • Пользователь
  • Сообщений: 1664
  • Пол: Мужской
  • Mens sana in corpore sano
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #21 : 22 Ноябрь 2023, 22:18:17 »
Будь ты проклят С++ новых стандартов))

Все просто, return делает выход из вашей функции в произвольном месте, за ним ничего уже не выполнится, можно не писать.
break будет переходом на следующий оператор за циклом, или у Вас тут за закрывающей операторный скобкой оператора switch. Используйте если хотите сделать только один из n выборов, иначе можно не писать, и код будет проваливаться на следующие проверки и дефолт

Оффлайн perfect_genius

  • Пользователь
  • Сообщений: 1159
    • ВКонтакте
    • Steam
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #22 : 23 Ноябрь 2023, 00:05:33 »
Тема перешла на основы программирования, ну да ладно. Явно ведь делаешь для хакинга ромов?
с if-else на switch, так как теперь нужен выбор из трех вариантов
If-Else можно продолжать:
if(chipType == 0){
   eraseSector22XX(addr);}

else
if(chipType == 1){
   for(int smallAddr = addr; smallAddr < addr + 0x8000; smallAddr += 0x2000)
   eraseSectorIntel(smallAddr);}

else
if(chipType == 2){
   eraseSharp();}

else{
   return;}

Оффлайн Talking_Sword

  • Пользователь
  • Сообщений: 903
  • Happy Games Only!
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #23 : 23 Ноябрь 2023, 16:53:03 »
Явно ведь делаешь для хакинга ромов?
Нет.
If-Else можно продолжать:
Знаю, но слышал, что этим увлекаться не стоит, якобы switch эффективнее. Думаю, может кто-нибудь здесь знает такого разработчика YandereDev? Слышал, что причина тормознутости его игры как раз в том, что он злоупотребляет if-else.

Спасибо всем за советы. Не смотря на предостережения от Sharpnull, все-таки решил убрать return и break из case 2. Chip Erase не запустилось два раза, а это значит, что без break переходит на следующий вариант (в принципе, я знал об этом, но не уверен, стал бы он переходить на default), а также return прерывает функцию вместе с работающим в ней циклом.

Правда скомпилировалось не сразу - в одном месте забыл восклицательный знак в "!=", а потом еще удивлялся, про какую же lvalue говорит мне компилятор. А в функции writeByWord вообще умудрился как-то уничтожить одну "родную" фигурную скобку, когда вставлял туда свой switch.

Но когда исправил ошибки, код заработал с перврго раза. Сегодня уже попробовал прошить LH28F800BJE - микросхема прошилась и даже не сдохла после двух раз (первый раз прошил другой ROM, во второй вернул "старый"). Также прошил MX29LV320E - тоже прошилась нормально.

Осталась только загвоздка с Device ID. В программе просто захардкожены несколько Device ID:

if (((flashid >> 8) & 0xFF) == 0x22 || flashid == 0x7E7E || flashid == 0x57 || flashid == 0xF8)
То есть, если программа не "видит" знакомого Device ID, то считает, что микросхема не определилась. Стоит обратить еще внимание на это: ((flashid >> 8) & 0xFF) == 0x22 - на сколько я понимаю, это проверка только старшего байта, а у многих микросхем старший байт Device ID = 0x22. Таким образом, видимо автор пытался охватить большее количество микросхем, не прописывая все их Device ID.

Тем не менее, у многих, но не у всех - есть микросхемы, у которых Device ID "не подходит", но при этом у них такая же система комманд, и Burn2Slot потенциально может их прошить. У меня например есть TC58FVB160AFT (Device ID=0x0043), SST39VF1601 (Device ID=0x23BH), SST39VF1602 (Device ID=0x23AH). Чисто в теории, в программе нужно сделать какую-то "базу данных" по Device ID, как это уже сделано с Manufacturer ID в файле "ID.H". Но этих Device ID просто море, нужно в интернете найти какой-то список, пока не нашел. Плюс ко всему, надо еще придумать, как программа будет перебирать их все. Но судя по всему, так и делают - нашел пример.

Но я пока не знаю, где бы взять базу данных по этим самым ID, и как их проверять. Пока придумал только довольно костыльный метод - до посылания комманды идентификации считываю данные по адресам 0x0 и 0x1, затем после комманды считываю значения по этим же самым адресам - если они изменились, то значит считаю, что микросхема откликнулась. Но это не очень хороший метод, плюс ко всему, подумал, что так не получится корректно определить busType.

P.S.: Кстати, нашел ошибку в ID.h - в case MACRONIX_ID автор забыл break. А ведь у меня микросхемы фирмы Macronix определялись как "Sharp" в Burn2Slot. Я это сразу заметил, но сначала не предал значения - думал, может у Macronix как-то изменился Manufacturer ID, может у меня какая-то старая микросхема, у которой Manufacturer ID как у Sharp. Ну или может купили производство Flash-памяти у Sharp, а ID остался старый.

Но оказалось там просто нет break, а так как сразу за Macronix идет Sharp, то его функция и возвращала.
« Последнее редактирование: 23 Ноябрь 2023, 17:00:53 от Talking_Sword »

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 5051
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #24 : 25 Ноябрь 2023, 17:23:46 »
слышал, что этим увлекаться не стоит, якобы switch эффективнее.
В сети есть обсуждение, switch действительно чаще работает быстрее, но обычно никто не пишет if (i==0) {} else if (i==1) {} else if (i==2) {} ... Эта запись тоже странная:
u16 ( *( read_word() ) )(u32 address)
{
switch(cart->busType) {
case 0: return read_word_rom;
case 1: return read_swapped_word_rom;
...
Сложно читать что возвращается, обычно пишут typedef для указателя на функцию, чтобы заменить на "Func read_word()". И я бы заменил на массив функций, чтобы записать Func read_word() { return func_arr[cart->busType]; }. Или можно просто делать нужный вызов void read_word(u32 address) { switch(cart->busType) { case 0: read_word_rom(address); ... }}, или, если нужны указатели на функции использовать func_arr[cart->busType], а обычный вызов - void read_word(u32 address) { func_arr[cart->busType](address); }, тогда вызов read_word() без доп. скобок.
может кто-нибудь здесь знает такого разработчика YandereDev? Слышал, что причина тормознутости его игры как раз в том, что он злоупотребляет if-else.
Там вообще Unity, а значит Mono (вероятно C#). Увидел запись по поводу Yandere Simulator, что проблема в if else, но смысл не в замене на switch (что можно только в определённых случаях), а что там вообще не должно быть проверок. Т. е. проблема на уровне алгоритмов. Этот говнокодер не заслуживает внимания.
Не смотря на предостережения от Sharpnull, все-таки решил убрать return и break из case 2.
Это конечно работает, но запутанно и ведёт к ошибкам.
нашел ошибку в ID.h - в case MACRONIX_ID автор забыл break
Как я писал, частая ошибка. Там же char* manufactur = (char*)malloc(sizeof(char) * 12);, но ниже manufactur = "Alliance"; в getManufacturByID(), т. е. зачем-то выделяется память без очищения (free()) и указатель на неё теряется после вызова getManufacturByID(). Этот баг не проявится, т. к. утечка один раз за работу программы, а после завершения программы память возвращается.
UPD:
Плюс ко всему, надо еще придумать, как программа будет перебирать их все.
Идентификаторы можно записать в массив и перебирать - медленно, но просто. Вместо кучи switch, можно использовать словари (std::unordered_map) или множества (std::set), которые быстро находят элемент или позволяют проверить наличие элемента. Также есть простой вариант с массивами: например, у нас id от 0 до 255, определяем массив:
const char* arr[] = {
/* 00 */   "ID00"
/* 01 */ , "ID01"
...
/* FF */ , "IDFF"
};
Тогда простая инструкция быстро даёт значение по ключу: str = arr[id]. Это https://en.wikipedia.org/wiki/Lookup_table.
« Последнее редактирование: 25 Ноябрь 2023, 17:37:12 от Sharpnull »

Оффлайн wolfer

  • Пользователь
  • Сообщений: 1664
  • Пол: Мужской
  • Mens sana in corpore sano
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #25 : 25 Ноябрь 2023, 18:10:00 »
Современные компиляторы так оптимизируют ваш код, что что бы вы не писали, будет одинаково быстро :D

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 5051
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #26 : 25 Ноябрь 2023, 20:46:11 »
что бы вы не писали, будет одинаково быстро
Нет, не всегда. Года 3 назад я тестировал скорость своей программы для сжатия, использование do {} while (в одном месте), MinGW, под x86 работало быстрее, чем while {}, Visual Studio, под x64. В сумме разница между худшим и лучшим вариантом могла выйти в 2 раза по времени работы, а это простая консольная программа. После всех обновлений нужно тестировать заново и конфигурация моего ПК уже другая.

Оффлайн wolfer

  • Пользователь
  • Сообщений: 1664
  • Пол: Мужской
  • Mens sana in corpore sano
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #27 : 25 Ноябрь 2023, 21:52:36 »
Нет, не всегда. Года 3 назад я тестировал скорость своей программы для сжатия, использование do {} while (в одном месте), MinGW, под x86 работало быстрее, чем while {}, Visual Studio, под x64. В сумме разница между худшим и лучшим вариантом могла выйти в 2 раза по времени работы, а это простая консольная программа. После всех обновлений нужно тестировать заново и конфигурация моего ПК уже другая.
Звучит весьма странно, х64 скорости тут не прибавит, Вы же понимаете. Ну адрес большей длины, на инструкцию jmp это как повлияет?) Вот именно VS оптимизирует все даже когда вы этого не хотите, весьма удивительно, что работает так. Скорее тут настройки проекта с отключенной оптимизацией по скорости и внутреннее содержимое цикла…
Но к моему утверждению это не относится, я же имел ввиду, что пиши хоть for, хоть while, хоть do while, результат после оптимизирующего компилятора может быть одинаковый, если компилятор один и тот же… И это не голословное утверждение, знаю о чем говорю

Добавлено позже:
Конечно, если написать неверный код и в одном случае выйдет больше вызовов требовательной к ресурсам функции, то и время работы программы изменится, но это как всегда дело не в бабине…

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 5051
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #28 : 25 Ноябрь 2023, 23:12:19 »
х64 скорости тут не прибавит, Вы же понимаете
Я не понимаю почему скорость падает на x64. Использовал size_t, intptr_t, поэтому возможно int32 быстрее int64 на x64 в том случае.
результат после оптимизирующего компилятора может быть одинаковый, если компилятор один и тот же… И это не голословное утверждение, знаю о чем говорю
Это очевидно, я писал, что "не всегда" и привёл свой пример в стандартной среде (MinGW/GCC с обычной оптимизацией -O2 и Visual Studio 2019 с обычным Release для пустой консольной программы).
Скорее тут настройки проекта с отключенной оптимизацией по скорости и внутреннее содержимое цикла…
Циклы такие, написал для https://godbolt.org:
Я не разбираюсь в x86 asm и по x86-64 gcc 13.2 с -O2 не понял есть ли разница. Может зависеть от предсказаний процессора, внешнего цикла и т. п. По идее, чаще будет cur_len == 1 для обычных файлов, где повторов не много. Мне следовало тестировать на разных файлах, включая полностью из нулей. Проверку ((spos + 1) + cur_len < src_len) можно убрать для большей части файла, когда до конца данных далеко. Ещё можно сделать "размотку цикла", но там как повезёт.
Ладно, много оффтопа, я закончил.

Оффлайн perfect_genius

  • Пользователь
  • Сообщений: 1159
    • ВКонтакте
    • Steam
    • Просмотр профиля
Картриджи под перепрошивку
« Ответ #29 : 26 Ноябрь 2023, 01:24:03 »
Talking_Sword, я согласен с wolfer, что компиляторы хорошо оптимизируют. Поэтому тебе надо думать над твоей задачей, а не париться над оптимизацией.

обычно никто не пишет if (i==0) {} else if (i==1) {} else if (i==2) {}
Когда этот список условий крутится в цикле, то хочется с помощью break выходить из него, а не из switch. Устанавливать условие, ломающее цикл - некрасиво и лишние действия. goto тоже обычно некрасиво :)

Я не понимаю почему скорость падает на x64.
64 занимает место в кэше в два раза больше, чем 32.