Pull to refresh

Comments 30

ну по одной кнопке, однозначно, не может. если провести аналогию, то программист тоже не пишет программу с первого раза. было бы интересно завернуть в автоматическом режиме вывод компилятора и ошибки рантайма в ЛЛМ. как это отлаживается человеком. спасибо за статью!

Пока не может. В ближайшем будущем тоже скорее всего не сможет, дальше посмотрим

Разумеется, и в данном опусе я анализирую данную предметную область с точки зрения человека, потратившего 0 рублей и 0 копеек на эксперименты. Платные решения я не анализировал - может есть чего там получше. Разумеется - это локальное мнение, которое зависит от контекста

ИИ может дать код хэлворда на опциональном язык. А чуть выше - затык, с которым приходиться ебаться разбираться. И анализировать. И понимать. Да - быстрее, в разы быстрее! В этом и посыл топика - использовать ИИ с умом

Платные так же глючат и галюцинируют. Ещё и задорого. Но модели там больше, и контексты в них соответсвующие, что позволяет например делать более пространные задания с кучей условий. Правда, написание грамотного промпта, занимает время порой сопоставимое с написанием кода, потом ИИ сгененрированного. Про отладку и поиск багов я молчу, ибо автор и сам это хорошо расписал. В любом случае - приходится погружаться в написанное ИИ, пытаться понять и проанализировать хотя бы примерную его логику, и лишь потом тыкать палочкой ИИ что и где править, или самому руками вносить правки и наказывать ему, чтобы больше в такой то участок не лез ( оч ем он очень быстро забывает обычно, из-за ограничения контекста)!

очень круто, спасибо за статью!

За положительный отзыв плюсую. В том что круто - не согласен, задачка довольно тривиальная

По моим наблюдениям, для программирования лучше deepseek, а qwen для математики. Платных тоже не пробовал.

Красиво!
Но попробуйте qwen-code (https://github.com/QwenLM/qwen-code)! Когда LLM может видеть весь проект, формировать себе долговременную память, запускать и отлаживать код у неё получается лучше, ни в коем случае неидеально, но куда как приятнее чем работать с чатами.

Система не может "формировать себе память", тем более долговременную. Память типа STM или LTM, либо изначально есть есть у системы, либо её нет, т.к. изначально учитывается на уровне архитектуры. В данный момент, проходят только эксперименты по созданию LTM у LLM, но пока это "дорогое удовольствие", в вычислительном плане и больше похожи на создание стабильной STM

На уровне LLM не может, а вот на агентном уровне, на котором работает qwen-code и ему подобные, очень даже может - дадите ему подходящий MCP - будет в векторной db, не дадите - текстом в файле сохранит.

Сами понимаете - это не решение, а костыль, а значит и не будет LTM в полном понимании данного термина, зато будет хорошая STM

У меня такой опыт. Даю задачу бесплатным - ни один не может решить, даже если по пол часа уточнять. Даю ту же задачу o3 - и он просто берет и решает, как будто какой то новый уровень.

Да, o3 - это прорыв. GPT5-codex еще на голову выше o3. Какой смысл делать обзор на инвалидные модели?

Какой смысл делать обзор на инвалидные модели?

Людям и бесплатные модели крышу сносит, а вы хотите вообще до клиники довести?

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

MOS 6502. Очень простой процессор - набор команд всего 56 инструкций, вместе со всеми режимами адресации дающий 151 вариант выполнения

Commodor 64. Вот на последнем я и остановился

Понимаю что статья несколько не об этом, но раз уж информация в статье есть, то напишу.

<душнила вкл>

  1. Commodore 64

  2. Эмуляция C64 сложна, даже в отличии от ATARI XL/XE, в том что нужно эмулировать видеочип, который несколько более навороченный чем в ATARI. Если уж хотели эмулировать MOS 6502, то можно же взять что-то без видеочипа.

<душнила выкл>

Просто я очень уважаю Джека Трэмэла. Узник Освенцима, выжил, построил свою жизнь на новом месте... Да, он капиталистическая акула, поглощавшая конкурентов. Но при этом его преследовали замечательные идеи, которые воплотились в C64.

Это чисто личное, тем более о Commodore 64 по-русски мало кто пишет

<картинка с Бендером у которого в голове 6502>

У первого терминатора тоже 6502

Интересно, кстати, почему у терминатора дизассемблерный листинг с комментариями?

А то, что это листинг создания каталога (VTOC) на $11-й дорожке дискеты, вас не смущает?

Это ассемблер, конечно, а не дизассемблер. Видать, правит свои исходники.

Многочисленные различные эмуляторы 6502 уже содержатся в обучающей выборке LLM, поэтому тут удивляться надо тому, что не заработало с первого раза.

Поисковый сервер google с той же задачей справляется гораздо лучше.

Всегда рад, что кому-то помогли мои статьи.

1) Вместо копипаста лучше подцепить плагин к ide, который будет бегать к БЯМке. Из самых главных плюсов - он будет видеть уже готовый код.

2) Запросы к БЯМке надо писать подробнее. Она, как ты уже понял, очень ленивая и любит схалтурить. Вместо "все 56 инструкций с точным счётом тактов" надо было что-то "Напиши эмулятор процессора 6210, используемый в commodore 64. Мне нужна функция, исполняющая один опкод, которая возвращает число тактов, потребленных этим опкодом. Реализуй все инструкции со свеми типами адресации максимально точно к официальной документации. Не пропускай даже самые незначительные нюансы". И тогда с первого раза получится уже более удобоваримое

Спасибо. Только что ткнул в deepseek дословно приведенным в 2) запросом - таки да, эта зараза сгенерировала аккуратно обработку всех опкодов, приведу фрагмент для команды ADC

switch (opcode) {
            // ADC Instructions
            case 0x69: { cycles = 2; adc(imm()); break; } // ADC imm
            case 0x65: { cycles = 3; adc(read(zpg())); break; } // ADC zpg
            case 0x75: { cycles = 4; adc(read(zpgX())); break; } // ADC zpg,X
            case 0x6D: { cycles = 4; adc(read(abs())); break; } // ADC abs
            case 0x7D: { cycles = 4 + pageCrossed; adc(read(absX(pageCrossed))); break; } // ADC abs,X
            case 0x79: { cycles = 4 + pageCrossed; adc(read(absY(pageCrossed))); break; } // ADC abs,Y
            case 0x61: { cycles = 6; adc(read(indX())); break; } // ADC (ind,X)
            case 0x71: { cycles = 5 + pageCrossed; adc(read(indY(pageCrossed))); break; } // ADC (ind),Y

Так что да, согласен, что любым инструментом надо учиться пользоваться, и происходит это с опытом

Нашел еще пару мест, уже в бейсике, где осуществляется зацикливание. Задушил принудительно, получил вывод бейсика - синтаксическая ошибка

Наверное придется теперь честно инициализировать клавиатуру. Но строчки весело бегут по экрану - исполняется код бейсика

я очень плохо понимаю чужой код, отсюда вопрос - я правильно понял что вы рисуете экран попиксельно? выдерживаете ли вы 60 фпс для генерации NTSC? я это не увидел?

Пардон за не быстрый ответ.

я правильно понял что вы рисуете экран попиксельно?

Да, совершенно правильно. Пока реализация такова

vic.cpp

//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
void VIC::render_text_mode(SDL_Renderer *render)
{
    //uint16_t screen_base = get_screen_base();
    uint16_t char_base = get_char_base();

    for (int y = 0; y < 25; ++y)
    {
        for (int x = 0; x < 40; ++x)
        {
            uint16_t screen_addr = y * 40 + x;
            uint8_t char_code = screen_ram[screen_addr];
            uint8_t color_idx = color_ram[screen_addr];

            Color bg = palette[regs[0x21] & 0x0F];
            Color fg = palette[color_idx];

            SDL_SetRenderDrawColor(render, bg.r, bg.g, bg.b, 255);
            SDL_Rect rect = {x * 8 * sf, y * 8 * sf, 8 * sf, 8 *sf};
            SDL_RenderFillRect(render, &rect);

            for (int py = 0; py < 8; ++py)
            {
                uint8_t row = char_rom[char_base + char_code * 8 + py];
                for (int px = 0; px < 8; ++px)
                {
                    if (row & (0x80 >> px))
                    {
                        SDL_SetRenderDrawColor(render, fg.r, fg.g, fg.b, 255);
                        //SDL_RenderDrawPoint(render, (x * 8 + px)*sf, (y * 8 + py)*sf);
                        draw_scale_pixel(render, (x * 8 + px)*sf, (y * 8 + py)*sf, sf);
                    }
                }
            }
        }
    }
}

sf - Scale Factor, для масштабирования. Так как окошечко в 320x200 пикселей на мониторе в 4к выглядит несолидно

выдерживаете ли вы 60 фпс для генерации NTSC? я это не увидел?

Пытаюсь

c64.cpp

//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
void C64::run()
{
    SDL_Window *window = SDL_CreateWindow("C64 Emulator",
                                          SDL_WINDOWPOS_CENTERED,
                                          SDL_WINDOWPOS_CENTERED,
                                          320 * sf,
                                          200 * sf,
                                          0);

    SDL_Renderer *render = SDL_CreateRenderer(window, -1, 0);

    const int TARGET_HZ = 1023000;
    const double CYCLE_TIME_NS = 1e9 / TARGET_HZ;
    int64_t total_cycles = 0;
    auto start = std::chrono::high_resolution_clock::now();

    while (is_running)
    {
        SDL_Event e;

        while (SDL_PollEvent(&e))
        {
            if (e.type == SDL_QUIT)
            {
                is_running = false;
            }
        }

        int step_cycles = cpu.execInstruction();

        cia1.tick(step_cycles);
        cia2.tick(step_cycles);

        vic.tick(step_cycles);        

        total_cycles += step_cycles;

        double elapsed = std::chrono::duration<double, std::nano>(
                             std::chrono::high_resolution_clock::now() - start
                             ).count();

        double target = total_cycles * CYCLE_TIME_NS;

        if (elapsed < target)
        {
            std::this_thread::sleep_for(std::chrono::nanoseconds((long long)(target - elapsed)));
        }

        static int frame_counter = 0;

        if (++frame_counter % (TARGET_HZ / 60) == 0)
        {
            vic.render(render);
            //vic.regs[0x12] = 0; // ЗАЦИКЛИВАНИЕ ПОДАВЛЕНО ПРИНУДИТЕЛЬНО!!!
            //cpu.irq();
        }
    }

    SDL_DestroyRenderer(render);
    SDL_DestroyWindow(window);
}

Привожу весь код цикла симуляции, чтобы был ясен контекст. Строки 52 - 59 это имитируют

спасибо за ответ

Sign up to leave a comment.

Articles