Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.87/82: Рейтинг темы: голосов - 82, средняя оценка - 4.87
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562

Эмулятор CHIP-8

10.08.2010, 06:34. Показов 16992. Ответов 90
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Мы с fasked написали простенький эмулятор для платформы CHIP-8.
CHIP-8
Остались вопросы по графике и клавиатуре. Если кто знает как реализовать - помогите, пожалуйста.
Так же приглашаем для участия в доработке этого проекта, а так же следующих проектах всех, кто желает учиться и трудиться.
Кому интересна работа эмулятора все вопросы к fasked)
Полный проект в прикрепленном архиве в сообщении ниже

CHIP8
types.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**************************************************************
* TYPES.H                                                     *
* Emulator CHIP-8                                             *
*                                                             *
* basic typedef and constants                                 *
*                                                             *
* LAST UPD: 09/08/2010                                        *
*                                                             *
* by Lavroff and fasked (c)                                   *
**************************************************************/
 
#ifndef HEADER_TYPES_H
#define HEADER_TYPES_H
 
typedef unsigned char  BYTE;
typedef unsigned short WORD;
 
#define DATA_REG_SIZE   16
#define ADDR_REG_SIZE   4096
#define STACK_SIZE      16
 
#define SCREEN_VER_SIZE 32
#define SCREEN_HOR_SIZE 64 
 
#define VIDEO_MEM_SIZE (SCREEN_HOR_SIZE * SCREEN_VER_SIZE)
 
#endif /* HEADER_TYPES_H */


chip-8.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/**************************************************************
* CHIP8.H                                                     *
* Emulator CHIP-8                                             *
*                                                             *
* basic declarations                                          *
*                                                             *
* LAST UPD: 09/08/2010                                        *
*                                                             *
* by Lavroff and fasked (c)                                   *
**************************************************************/
 
#ifndef _HEADER_CHIP8_H_
#define _HEADER_CHIP8_H_
 
#include "types.h"
 
//Declaration of global variables and arrays
static BYTE dataRegisters[DATA_REG_SIZE];
static BYTE addrRegisters[ADDR_REG_SIZE];
 
static WORD stackMemory[STACK_SIZE];
static BYTE videoMemory[VIDEO_MEM_SIZE];
 
static BYTE soundTimer;
static BYTE delayTimer;
 
static WORD iRegister;
 
static BYTE stackCounter;
static WORD offsetMemory;
 
const static BYTE font[80] = { 
   0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
   0x20, 0x60, 0x20, 0x20, 0x70, // 1
   0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
   0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
   0x90, 0x90, 0xF0, 0x10, 0x10, // 4
   0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
   0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
   0xF0, 0x10, 0x20, 0x40, 0x40, // 7
   0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
   0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
   0xF0, 0x90, 0xF0, 0x90, 0x90, // A
   0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
   0xF0, 0x80, 0x80, 0x80, 0xF0, // C
   0xE0, 0x90, 0x90, 0x90, 0xE0, // D
   0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
   0xF0, 0x80, 0xF0, 0x80, 0x80  // F
};
 
//Declaration of macro
#define START_OFFSET 200
 
#define DATA_REG_VX(n)\
   (dataRegisters[(0x0F00 & n) >> 8])
 
#define DATA_REG_VY(n)\
   (dataRegisters[(0x00F0 & n) >> 4])
 
#define DATA_REG_VF\
   (dataRegisters[0xF])
 
#define DATA_REG_V0\
   (dataRegisters[0x0])
 
//Declaration of functions
void InitialiseEmulator();
void EmulatorRun();
 
void LoadOpcodes(WORD * opcodes);
 
WORD GetOpcode();
void ExecuteOpcode (WORD opcode);
 
void ExecuteOpcode0(WORD opcode);
void ExecuteOpcode1(WORD opcode);
void ExecuteOpcode2(WORD opcode);
void ExecuteOpcode3(WORD opcode);
void ExecuteOpcode4(WORD opcode);
void ExecuteOpcode5(WORD opcode);
void ExecuteOpcode6(WORD opcode);
void ExecuteOpcode7(WORD opcode);
void ExecuteOpcode8(WORD opcode);
void ExecuteOpcode9(WORD opcode);
void ExecuteOpcodeA(WORD opcode);
void ExecuteOpcodeB(WORD opcode);
void ExecuteOpcodeC(WORD opcode);
void ExecuteOpcodeD(WORD opcode);
void ExecuteOpcodeE(WORD opcode);
void ExecuteOpcodeF(WORD opcode);
 
void RedrawScreen();
void Delay();
void SoundPlay();
 
#endif /* HEADER_CHIP8_H */


chip8.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
#include <iostream>
#include <windows.h>
#include "chip8.h"
 
void RedrawScreen()
{
   system("cls");
   for(int i = 0; i < SCREEN_HOR_SIZE; ++i)
   {
      for(int j = 0; j < SCREEN_VER_SIZE; ++j)
      {
         if(videoMemory[i * SCREEN_HOR_SIZE + j])
            printf("*");
         else
            printf(" ");
      }
 
      printf("\n");
   }
}
 
void Delay()
{
   if(delayTimer)
   {
      Sleep(delayTimer*1000);
   }
}
 
void SoundPlay()
{
   if(soundTimer)
   {
      for(int i=0;i<soundTimer;++i)
         std::cout<<'\a'<<std::endl;
   }
}
 
void InitialiseEmulator()
{
   stackCounter = 0;
   soundTimer = 0;
   delayTimer = 0;
 
   offsetMemory = START_OFFSET;
   iRegister = START_OFFSET;
 
   memset(dataRegisters, 0, DATA_REG_SIZE * sizeof(BYTE));
   memset(addrRegisters, 0, ADDR_REG_SIZE * sizeof(BYTE));
   memset(videoMemory, 0, VIDEO_MEM_SIZE * sizeof(BYTE));
   memset(stackMemory, 0, STACK_SIZE * sizeof(WORD));
   memcpy(addrRegisters, font, 80);
}
 
void LoadOpcodes(WORD * opcodes)
{
   memcpy(addrRegisters + offsetMemory, opcodes, ADDR_REG_SIZE * sizeof(BYTE));
}
 
WORD GetOpcode()
{
   return *(WORD*)(addrRegisters + offsetMemory); // TODO исправить на более правильный вариант
}
 
void EmulatorRun()
{
   WORD opcode = 0;
   for(;;)
   {
      opcode = GetOpcode();
//#ifdef _DEBUG
//      printf("%s: %#0.4x | %s: %#0.4x\n", "OFFSET", offsetMemory, "OPCODE", opcode);
//#endif
 
      if(opcode == 0)
         break;
 
      ExecuteOpcode(opcode);
 
      offsetMemory += 2;
 
      SoundPlay();
      Delay();
      //RedrawScreen();
   }
}
 
void ExecuteOpcode0(WORD opcode)
{
   if((opcode & 0x00FF) == 0xE0)
      memset(videoMemory, 0, VIDEO_MEM_SIZE * sizeof(BYTE)); // 0x00E0: Clear the Screen
   
   else if((opcode & 0x00FF) == 0xEE)
   {
      --stackCounter;
      offsetMemory = stackMemory[stackCounter];
   }
 
   else if((opcode & 0xF000) == 0)
   {
      //TODO 0NNN-Opcode
   }
}
 
void ExecuteOpcode1(WORD opcode)
{
   offsetMemory = opcode & 0x0FFF;
}
 
void ExecuteOpcode2(WORD opcode)
{
   if(stackCounter < 16)
   {
      stackMemory[stackCounter] = offsetMemory;
      ++stackCounter;
   }
 
   offsetMemory = opcode & 0x0FFF;
}
 
void ExecuteOpcode3(WORD opcode)
{
   if(DATA_REG_VX(opcode) == (opcode & 0x00FF))
      offsetMemory += 2;
}
 
void ExecuteOpcode4(WORD opcode)
{
   if(DATA_REG_VX(opcode) != (opcode & 0x00FF))
      offsetMemory += 2;
}
 
void ExecuteOpcode5(WORD opcode)
{
   if(DATA_REG_VX(opcode) == DATA_REG_VY(opcode))
      offsetMemory += 2;
}
 
void ExecuteOpcode6(WORD opcode)
{
   DATA_REG_VX(opcode) = 0x00FF & opcode;
}
 
void ExecuteOpcode7(WORD opcode)
{
   DATA_REG_VX(opcode) += 0x00FF & opcode;
}
 
void ExecuteOpcode8(WORD opcode)
{
   if((opcode & 0xF) == 0x0)
      DATA_REG_VX(opcode) = DATA_REG_VY(opcode);
   
   else if((opcode & 0xF) == 0x1)
      DATA_REG_VX(opcode) |= DATA_REG_VY(opcode);
 
   else if((opcode & 0xF) == 0x2)
      DATA_REG_VX(opcode) &= DATA_REG_VY(opcode);
 
   else if((opcode & 0xF) == 0x3)
      DATA_REG_VX(opcode) ^= DATA_REG_VY(opcode);
 
   else if((opcode & 0xF) == 0x4)
   {
      WORD t = DATA_REG_VX(opcode) + DATA_REG_VY(opcode);
      DATA_REG_VX(opcode) = (BYTE)t;
      DATA_REG_VF = (BYTE)(t & 0x100); 
   }
 
   else if((opcode & 0xF) == 0x5)
   {
      WORD t = DATA_REG_VX(opcode) - DATA_REG_VY(opcode);
      DATA_REG_VX(opcode) = (BYTE)t;
      DATA_REG_VF = (BYTE)((t & 0x100) >> 8);
   }
 
   else if((opcode & 0xF) == 0x6)
   {
      DATA_REG_VF = DATA_REG_VX(opcode) & 1;
      DATA_REG_VX(opcode) >>= 1;
   }
 
   else if((opcode & 0xF) == 0x7)
   {
      WORD t= DATA_REG_VY(opcode)- DATA_REG_VX(opcode);
      DATA_REG_VX(opcode) = (BYTE)t;
      DATA_REG_VF = (BYTE)((t & 0x100) >> 8);
   }
 
   else if((opcode & 0xF) == 0xE)
   {
      DATA_REG_VF = DATA_REG_VX(opcode) & 0x80;
      DATA_REG_VX(opcode) <<= 1;
   }
}
 
void ExecuteOpcode9(WORD opcode)
{
   if(DATA_REG_VX(opcode) != DATA_REG_VY(opcode))
      offsetMemory+=2;  
}
 
void ExecuteOpcodeA(WORD opcode)
{
   iRegister = opcode & 0x0FFF;
}
 
void ExecuteOpcodeB(WORD opcode)
{
   offsetMemory = (opcode & 0x0FFF) + dataRegisters[0];
}
 
void ExecuteOpcodeC(WORD opcode)
{
   DATA_REG_VX(opcode) = (BYTE)(rand()) & (opcode & 0x00FF);
}
 
void ExecuteOpcodeD(WORD opcode)
{
   // TODO D-opcode
   WORD x = DATA_REG_VX(opcode);
   WORD y = DATA_REG_VY(opcode);
   WORD h = opcode & 0x000F;
 
   for(int i = 0; i < h; ++i)
   {
      WORD data = addrRegisters[i + iRegister];
      
      for(int j = 0; j < 8; ++j)
      {
         if((data & (0x80 >> i)) != 0)
         {
            if(videoMemory[j + x + (( y + i ) * SCREEN_HOR_SIZE)] == 1)
               DATA_REG_VF = 1;
            else
               DATA_REG_VF=0;
 
            videoMemory[j + x + (( y + i ) * SCREEN_HOR_SIZE)] ^= 1;
         }
      }
   }
}
 
void ExecuteOpcodeE(WORD opcode)
{
  if((opcode & 0x00FF) == 0x9E)
  {
     // TODO EX9E-Opcode. Keyboard
  }
  else if((opcode & 0x00FF) == 0xA1) 
  {
     // TODO EXA1-Opcode. Keyboard
  }
}
 
void ExecuteOpcodeF(WORD opcode)
{
  if((opcode & 0x000F) == 0x7)
     DATA_REG_VX(opcode) = delayTimer;
 
  else if((opcode & 0x000F) == 0xA)
  {
     //TODO FX0A opcode
  }
  
  else if((opcode & 0x00FF) == 0x15)
     delayTimer = DATA_REG_VX(opcode);
  
  else if((opcode & 0x00FF) == 0x18)
     soundTimer = DATA_REG_VX(opcode);
  
  else if((opcode & 0x00FF) == 0x1E)
     iRegister += DATA_REG_VX(opcode);
  
  else if((opcode & 0x00FF) == 0x29)
  {
     iRegister=DATA_REG_VX(opcode);
  }
  
  else if((opcode & 0x00FF) == 0x33)
  {
     addrRegisters[iRegister] = DATA_REG_VX(opcode) / 100;
     addrRegisters[iRegister + 1] = (DATA_REG_VX(opcode) % 100) / 10;
     addrRegisters[iRegister + 2] = DATA_REG_VX(opcode) % 10;
  }
  
  else if((opcode & 0x00FF) == 0x55)
  {
     for(int i = 0; i < ((opcode & 0x0F00) >> 8); ++i)
        addrRegisters[i + iRegister] = dataRegisters[i];  
  }
  
  else if((opcode & 0x00FF) == 0x65)
  {
     for(int i = 0; i < ((opcode & 0x0F00) >> 8); ++i)
        dataRegisters[i] = addrRegisters[i + iRegister];
  }
} 
 
void ExecuteOpcode(WORD opcode)
{
  WORD opcodeGroup = opcode >> 12; // выделить старшие 4 бита
 
  switch(opcodeGroup)
  {
  case 0x0:
     ExecuteOpcode0(opcode);
     break;
  case 0x1:
     ExecuteOpcode1(opcode);
     break;
  case 0x2:
     ExecuteOpcode2(opcode);
     break;
  case 0x3:
     ExecuteOpcode3(opcode);
     break;
  case 0x4:
     ExecuteOpcode4(opcode);
     break;
  case 0x5:
     ExecuteOpcode5(opcode);
     break;
  case 0x6:
     ExecuteOpcode6(opcode);
     break;
  case 0x7:
     ExecuteOpcode7(opcode);
     break;
  case 0x8:
     ExecuteOpcode8(opcode);
     break;
  case 0x9:
     ExecuteOpcode9(opcode);
     break;
  case 0xA:
     ExecuteOpcodeA(opcode);
     break;
  case 0xB:
     ExecuteOpcodeB(opcode);
     break;
  case 0xC:
     ExecuteOpcodeC(opcode);
     break;
  case 0xD:
     ExecuteOpcodeD(opcode);
     break;
  case 0xE:
     ExecuteOpcodeE(opcode);
     break;
  case 0xF:
     ExecuteOpcodeF(opcode);
     break;
  }
}


main.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include "chip8.h"
 
int main()
{
   // массив опкодов
   // в дальнейшем должны читаться из файлов 
   // специально откомпилированнынх под CHIP-8
   WORD opcodes[ADDR_REG_SIZE] = { 0x6000, 0x6100, 0xA222, 0xC201, 
                                   0x3201, 0xA2E1, 0xD014, 0x7004, 
                                   0x3040, 0x1204, 0x6000, 0x7104, 
                                   0x3120, 0x1204, 0x121C, 0x8040, 
                                   0x2010, 0x2040, 0x8010, 0x0000
   };  
 
   // Инициализация ЦПУ эмулятора
   // очистка памяти, сброс счетчиков и таймеров
   InitialiseEmulator();
 
   // Загрузка опкодов в память эмулятора
   LoadOpcodes(opcodes);
 
   // Запуск эмулятора
   EmulatorRun();
 
   return 0;
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
10.08.2010, 06:34
Ответы с готовыми решениями:

Эмулятор. На С, С++
Здравствуйте уважаемые читатели форума! У меня такой вопрос: (СРАЗУ ПРЕДУПРЕЖДАЮ Я НЕ ОЧЕНЬ ХОРОШО РАЗБИРАЮСЬ ПОКА В ЭТОМ ТАК ЧТО ОЧЕНЬ...

Эмулятор телефона. С++
Эмулятор работы телефона. Телефон живёт своей жизнью может садиться батарея, а когда она сядет - батарея может зарядиться до 100%...

Эмулятор мышки
Здравствуйте все. Хотелось бы узнать, как можно на компьютере1 управлять курсором с помощью компьютера2 через USB-вход на компьютере1, так,...

90
11.08.2010, 12:04
Студворк — интернет-сервис помощи студентам

Не по теме:

Цитата Сообщение от Евгений М. Посмотреть сообщение
На Qt я не профи. SDK и книгу скачал вчера, сегодня с утра начал все компилировать.
а вроде не гентушник :) можно же было просто инсталятор скачать.

0
Мат в 32 хода
 Аватар для nikkka
237 / 172 / 18
Регистрация: 10.09.2009
Сообщений: 1,096
11.08.2010, 12:08
Цитата Сообщение от Евгений М. Посмотреть сообщение
SDK и книгу скачал вчера, сегодня с утра начал все компилировать.
скажи где если не трудно, а то я перерыл интернет, скачал книгу, а с SDK не могу разобратся...
0
1552 / 918 / 193
Регистрация: 26.03.2010
Сообщений: 3,105
11.08.2010, 12:12
Дак это, http://qt.nokia.com/downloads/
1
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
11.08.2010, 13:53
Цитата Сообщение от Евгений М. Посмотреть сообщение
Прямо в main().
Насчет вывода (монитора). В этом же main() создай новый поток (читайте про класс QThread), который будет отвечать за монитор (а может бы и за нажатые клавиши).
По поводу вызова функции, запускающей эмулятор в main не согласен. В конце концов пользователь должен сначала как-то загрузить файл в эмулятор, пусть это делается через слот главной формы.
С потоками пока что не разбирался, запустил все просто так. Ужасно устал, поэтому с потоками разберусь чуть позже. Чтение файла пока тоже не сделал - так что опкоды опять забиты вручную.
В общем набросал минимальный интерфейс так сказать
С прорисовкой вроде бы разобрался.
Выкладываю проект с исходниками и откомпилированной под Windows программой + необходимые для запуска библиотеки. За счет библиотек архив весит довольно много (QtGui4.dll, QtCore4.dll, mingwm10.dll, libgcc_s_dw2-1.dll). Однако они необходимы для запуска, если на машине они не установлены и не прописаны пути к ним.

Теперь влегкую опишу интерфейс и планы на счет него.

Меню File. Включает в себя стандартные пункты. открытие файла и выход из программы. Открытие файла не реализовано. Выводится только стандартный диалог. Но далее ничего не происходит - поставил заглушку.
Меню Emulator. Пока что включает только пункт запуска.
Меню View. Включает подменю для изменения размера одного пиксела. В идеале планирую сделать, чтобы размер пиксела вычислялся в зависимости от размера главного окна.
В меню Help помещен простенький модальный диалог About.

Для запуска теста вывода цифр надо выполнить команду Run из меню Emulator.

Код на данный момент грязноватый, сейчас немного отдохну и почищу его.

Хм. 5-мегабайтовый архив почему отказывается загружаться. Поэтому выложу только скриншот
Позже залью файлы на какой-нибудь файлообменник или открою FTP-доступ к себе.

Пойду отдыхать...
Миниатюры
Эмулятор CHIP-8  
2
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
12.08.2010, 06:09
Немного еще подработали прототип, опять нашли косяки с видеопамятью. Поправили.
Получили первый опыт работы с SVN - очень интересно надо сказать

В общем вот ссылка на наш репозиторий http://svn2.xp-dev.com/svn/chip8/, а это конкретно на архив с последним exe'шником http://svn2.xp-dev.com/svn/chi... /chip8.ZIP.

С потоками так и не начали разбираться. Не очень далеко-то мы продвинулись за эту ночь.

Из того, что сделали: добавление открытие файлов из диалога. Теперь эмулятор работает с файлами. Убрали возможность изменения размера пиксела. Решили, что лучше сразу сделать автоматический расчет, но позже, чем сейчас подобными вещами засорять код.

Эмулятор отрабатывает на бинарниках, которые не содержат опкодов для работы с клавиатурой (по нашему предположению). Так что он умеет сейчас только выводить картинки

Например так как в прикрепленном скриншоте. Этот бинарник приложен в архиве с программой.
Если пробовать запускать не-картинко-выводящие приложения, то эмулятор вешается. Опять же по предположению эмулятор ожидает какого-либо ввода с клавиатуры, например выбора пункта меню, а так как вывод на экран сейчас производится только после завершения программы, то эмулятор продолжает ждать вечно.
Миниатюры
Эмулятор CHIP-8  
2
1080 / 1007 / 107
Регистрация: 28.02.2010
Сообщений: 2,889
12.08.2010, 06:47
Лучший ответ Сообщение было отмечено как решение

Решение

Ого. Мне кажется есть недочеты.
1. Нажимаю на View ничего не появляется (Раз убрали возможность изменения размера точки думаю лучше убрать).
2. Запустил. File->Open->IBM Logo.c8. Далее лучше расширить экран, чтобы увидеть весь рисунок (см. вложение).
3. Думаю отступов между точками не должно быть.

Не очень далеко-то мы продвинулись за эту ночь.
Я так не думаю. Исходники появились, изучил SVN... и первое и второе очень большой шаг.

Насчет расчета размера точки (первое что пришло в голову).
Для начала. Ограничим изменение размера окна так, чтобы минимальная область, где все рисуется, имела параметры 64x32 (Если будет очень мелко можно повысить). Далее нужно сделать так, чтобы окно изменяла размер "только по диагонали". Насчет длины стороны квадратика (отвечающую за точку) думаю без меня ясно как вычислять - длина области / 64 либо длина высоты / 32 (целочисленное деление). Это немного смущает, но нужно попробовать на практике. Если действительно выглядит некрасиво то придумать че-нить другое.

Кстати в том SVN библиотеки как отдельный архив может быть поставишь?
Миниатюры
Эмулятор CHIP-8  
3
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
12.08.2010, 06:59
Цитата Сообщение от Евгений М. Посмотреть сообщение
Ого. Мне кажется есть недочеты.
Недочеты само собой есть
Почти обо всех перечисленных мы в курсе, но спасибо Вам за бдительность!
По поводу того, что необходимо расширить экран, чтобы увидеть полноценное лого. Честно, говоря, я просто забыл уменьшить размер одного пиксела по умолчанию.
Интерфейс-интерфейсом, однако сейчас считаю наиболее приоритетной задачей - это обеспечить правильность работы эмулятора, а не его внешнего вида.
Еще раз спасибо Вам за внимание к этому топику.
Цитата Сообщение от Евгений М. Посмотреть сообщение
Кстати в том SVN библиотеки как отдельный архив может быть поставишь?
хорошо, выложу библиотеки отдельным архивом в корень trunc, а в каталогах версий буду выкладывать архивы без них.
Я так распределил файлы из соображений, что кому библиотеки не нужны и из исходников соберет, а библиотеки в архив, потому что как-то нелогично саму программу и компоненты, обспечивающие работоспособность программы, ложить в разных местах.
1
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
13.08.2010, 02:07
Привертел миленькую виртуальную клавиатурку
Она наполнена багами, неизвестного мне происхождения, но благодаря ей, наконец-то удалось проработать логику работы с клавиатурой вообще. Теперь можно расширять до любого абстрактного устройства с 16-ю кнопками. Для вызова виртуальной клавиатуры добавил в меню "Emulator" пункт "Virtual Keyboard".
Миниатюры
Эмулятор CHIP-8  
2
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
13.08.2010, 07:53
Очередное утреннее обновление

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

Перерисовка экрана происходит 1 раз в секунду.

Очевидная проблема в том, что такие потоки ужасно нагружают процессор, лично у меня хавает порядка 50%. Пока что не знаю, как это решать.

Немного подправил работу с виртуальной клавиатурой. Однако же она все прячется при сворачивании главное окна, при восстановлении не появляется. Пока что сделал ее всегда поверх всех окон. Так во всяком случае ее хотя бы можно отключить.

Наконец-то приучил эмулятор открывать файлы поочереди, правда для этого желательно после запуска первой программы нажать кнопочку "Stop" из меню "Emulator".
Да. Из-за нагрузки на процессор программы опять же открывать не рекомендуется. Учитывая мой первый опыт я мог что-то накосячить с потоками, мало ли какие ошибки посыпятся, но у себя вроде не замечал.

В общем все. Опять приведу ссылки на новые версии:
Библиотеки, необходимые для запуска
.EXE файл программы и пара примеров
Исходники
1
1080 / 1007 / 107
Регистрация: 28.02.2010
Сообщений: 2,889
13.08.2010, 08:18
Так у нас дела очень серьезные... См. вложение.
Все проблемы связаны с запуском Chip8 emulator Logo [Garstyciuks].c8
Если я скомпилирую исходники и запущу этот файл появляется bug1.gif.
Если я возмьму скомпилированую прогу и запущу этот файл появляется bug2.gif. Нажимаю на OK появляется bug3.gif.
С IBM Logo все нормально в обеих случаях.

Исходники скопировал (svn выдал revision 9) попробую разобраться.
Моя ОС: WinXP SP3 Original
Вложения
Тип файла: zip bugs.zip (59.7 Кб, 11 просмотров)
1
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
13.08.2010, 09:10
Цитата Сообщение от Евгений М. Посмотреть сообщение
Так у нас дела очень серьезные... См. вложение.
Все проблемы связаны с запуском Chip8 emulator Logo [Garstyciuks].c8
Если я скомпилирую исходники и запущу этот файл появляется bug1.gif.
Если я возмьму скомпилированую прогу и запущу этот файл появляется bug2.gif. Нажимаю на OK появляется bug3.gif.
С IBM Logo все нормально в обеих случаях.

Исходники скопировал (svn выдал revision 9) попробую разобраться.
Моя ОС: WinXP SP3 Original
Версия правильная, странно, у себя такой проблемы не наблюдая, пробовал на Win7 и на WinXP SP3. Посмотрите у себя, пожалуйста. Мне сложно искать ошибку, не наблюдая ее.

Добавлено через 46 минут
начал просматривать исходники, нашел глупую ошибку, но врядли она имеет отношение к тем багам, что вы показали. просто клавиатура оказывалась бесполезной.
файл keyboard.cpp 66 строка:
правильно сравнивать
C++
1
if(w == buttons[i])
когда было
C++
1
if(w == this)
даже не знаю как допустил такую нелепость
0
1080 / 1007 / 107
Регистрация: 28.02.2010
Сообщений: 2,889
13.08.2010, 12:36
Лучший ответ Сообщение было отмечено как решение

Решение

Те баги, которые у меня появлялись я так и не смог исправить
Но мне кажется, что собака зарыта в функции ExecuteOpcodeD (chip8.cpp).

Теперь предложу свою поправку (см. вложение).
1. Убрал интервал обновления экрана (на мой взгляд это логичнее);
2. Поправил функцию рисования точек. Теперь где нули - там будут рисоваться черные точки, где 1 - белые. На мой взгляд так правильнее. К примеру возьмем анимацию, где точка идет по траектории прямоугольника. Если эту часть кода оставить без изменений, то после 1 круга эту точку не будет видно. Будет виден сам прямоугольник.

Теперь насчет оформление кода.
1. Функции процессора CHIP8 на мой взгляд должны находится в файле cpu.cpp;
2. Я посмотрел на некоторые исходники OpenSource программ и увидел, там табуляция либо с 4 пробелами либо как символ №9 из ASCII таблицы. В быту я использую символ №9, т.к. на мой взгляд этот символ для этого и предназначали.
Может быть все поправим табуляцию в исходниках? Это можно сделать автоматически. Скачайте http://www.nodesoft.com/search... fault.aspx и замените 3 пробела на "символ №9" (ALT+009).
3. Может быть оформим видеопамять как двухмерный массив? Так удобнее и логичнее.

Теперь насчет SVN.
Думаю лучше создать каталог branches рядом с tags и trunc, чтобы пользователи могли оставлять свои ревизии исходников.
Вложения
Тип файла: zip display.zip (654 байт, 16 просмотров)
3
1080 / 1007 / 107
Регистрация: 28.02.2010
Сообщений: 2,889
13.08.2010, 13:03
Кстати насчет вывода на экран. Может быть прямо из ExecuteOpcodeD вызывать процедуру рисования точки на экран?
0
1080 / 1007 / 107
Регистрация: 28.02.2010
Сообщений: 2,889
13.08.2010, 17:27
Думаю, что нашел источник багов у себя.
Смотрим, что я добавил в коде:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
void ExecuteOpcodeD(WORD opcode)
{
   // TODO
   // Check D-opcode
 
 
   WORD x = DATA_REG_VX(opcode);
   WORD y = DATA_REG_VY(opcode);
   WORD h = opcode & 0x000F;
   WORD w = 8;
 
   if(h == 0)
   {
      h = 16;
      w = 16;
   }
   
    
 
   BYTE data;
 
   for(int i = 0; i < h; ++i)
   {
      data = addrRegisters[iRegister + i];
 
      for(int j = 0; j < w; ++j)
      {
         if((data & (0x80 >> j)) != 0)
         {
         
           // Что ниже добавил я
            // Если появится сообщение - значит плохо
            if (j+x > 64) fprintf (pFile, "x+j=%d\n",j+x);
            if (i+y > 32) fprintf (pFile, "y+i=%d\n",y+i);
            // Что выше добавил я*/
 
            if(videoMemory[i + y + (( j + x ) * SCREEN_VER_SIZE)] == 1)
               DATA_REG_VF = 1;
            else
               DATA_REG_VF = 0;
 
            videoMemory[i + y + (( j + x ) * SCREEN_VER_SIZE)] ^= 1;
         }
      }
   }
}
Также добавил stdio.h, fopen("myfile.txt", "w") и т.д.
Результаты вложил.
Вложения
Тип файла: zip myfile.zip (555.6 Кб, 16 просмотров)
2
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
13.08.2010, 20:48
Цитата Сообщение от Евгений М. Посмотреть сообщение
1. Функции процессора CHIP8 на мой взгляд должны находится в файле cpu.cpp;
Я вообще в будущем многое что планировал перенести в сам класс CPU.
Просто добавил его только с утра.
Цитата Сообщение от Евгений М. Посмотреть сообщение
Я посмотрел на некоторые исходники OpenSource программ и увидел, там табуляция либо с 4 пробелами либо как символ №9 из ASCII таблицы. В быту я использую символ №9, т.к. на мой взгляд этот символ для этого и предназначали.
Может быть все поправим табуляцию в исходниках? Это можно сделать автоматически. Скачайте http://www.nodesoft.com/search... fault.aspx и замените 3 пробела на "символ №9" (ALT+009).
Нет, мы заранее договорились использовать 3 пробела.
Цитата Сообщение от Евгений М. Посмотреть сообщение
Убрал интервал обновления экрана (на мой взгляд это логичнее);
Об этом надо подумать. Не знаю насколько осмысленно постоянно заставлять обновлять содержимое окна.
Цитата Сообщение от Евгений М. Посмотреть сообщение
Поправил функцию рисования точек. Теперь где нули - там будут рисоваться черные точки, где 1 - белые. На мой взгляд так правильнее. К примеру возьмем анимацию, где точка идет по траектории прямоугольника. Если эту часть кода оставить без изменений, то после 1 круга эту точку не будет видно. Будет виден сам прямоугольник.
С этим согласен. Спасибоо.
Цитата Сообщение от Евгений М. Посмотреть сообщение
Может быть оформим видеопамять как двухмерный массив? Так удобнее и логичнее.
Думаю, мы сможем обойтись одномерным. Если хорошенько поразмышлять
Цитата Сообщение от Евгений М. Посмотреть сообщение
Теперь насчет SVN.
Думаю лучше создать каталог branches рядом с tags и trunc, чтобы пользователи могли оставлять свои ревизии исходников.
Честно, я не знаю как это сделать. Этот SVN-хостер требует включения участника в разработку проекта, чтобы выделить права на запись или чтение средствами SVN.
Цитата Сообщение от Евгений М. Посмотреть сообщение
Кстати насчет вывода на экран. Может быть прямо из ExecuteOpcodeD вызывать процедуру рисования точки на экран?
Не думаю, что это логично. Понятия, как таковы разные на физическом уровне, разные абстракции должны этим заниматься.
Цитата Сообщение от Евгений М. Посмотреть сообщение
Думаю, что нашел источник багов у себя.
Смотрим, что я добавил в коде:
Вот тут вы скорее всего правы. Спасибо за находку, буду разбираться, вылет и правда возможен.

Добавлено через 2 часа 56 минут
Почитав опкоды этого файла (заставки chip-8) обнаружил опкоды, которые отсутствуют в таблице, наверное эта программа для одной из модификаций приставки с увеличенным количеством памяти.
0
1080 / 1007 / 107
Регистрация: 28.02.2010
Сообщений: 2,889
13.08.2010, 21:12
Цитата Сообщение от fasked Посмотреть сообщение
которые отсутствуют в таблице
Т.е не отсюда?: http://www.pdc.kth.se/~lfo/chip8/CHIP8.htm
Если эта таблице не из википедии и если не трудно, поделитесь ссылкой.
0
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
13.08.2010, 21:40
Цитата Сообщение от Евгений М. Посмотреть сообщение
При создании обработчика опкодоа мы пользовались таблицей из википедии и этой ссылкой, находил еще пару ресурсов, сейчас ссылки уже не помню, но таблицы везде совпадали.
Если же открыть файл логотипа CHIP8 и просмотреть его в HEX виде, то там можно найти такие опкоды EA02, FA02... которые не попадают ни под один из таблиц.
0
1080 / 1007 / 107
Регистрация: 28.02.2010
Сообщений: 2,889
13.08.2010, 22:42
Ну... На мой взгляд эти опкоды лучше просто игнорировать. Если в дальнейшем игрушки будут криво играться может быть вернемся к этому вопросу.
0
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
13.08.2010, 22:47
Цитата Сообщение от Евгений М. Посмотреть сообщение
Ну... На мой взгляд эти опкоды лучше просто игнорировать. Если в дальнейшем игрушки будут криво играться может быть вернемся к этому вопросу.
да они сейчас и игнорируются. а проблема при выполнении, которую вы наблюдали в DXYN опкоде в том, что в регистрах VX и VY находится слишком большое значение адресов, которые выходят за предело 2Кб видеопамяти в нашей версии. Соответственно я и предположил, что программа для расширенной версии платформы. Предположения подтвердились нахождением левых опкодов.
0
1080 / 1007 / 107
Регистрация: 28.02.2010
Сообщений: 2,889
13.08.2010, 22:51
Цитата Сообщение от fasked Посмотреть сообщение
Соответственно я и предположил, что программа для расширенной версии платформы.
Это как понять?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
13.08.2010, 22:51

Эмулятор SetTimer
Ребята, подскажите, как написать функцию на подобие SetTimer. Дело в том, что используя std::thread, не дожидаясь завершение потока,...

Эмулятор клавиатуры
Привет. Нужно сделать програму которая при нажатии глобальных клавиш писала какойта текст. Как будто пользователь введёт его с клавиатуры....

Эмулятор трёхадресной машины.
В общем, имеется задача &quot;Эмулятор трёхадресной машины&quot;. Каждая инструкция имеет следующий формат: код инструкции (1 байт), операнд 1...

Эмулятор Вебки под Seven
Всем привет. Я проект пишу на С++, свой первый, более мене серьезный. Мне нужен эмулятор Веб камеры, но только что бы на Sevene работал......

Реализовать эмулятор командной строки
Реализовать эмулятор командной строки. Программа должна выполнять следующие функции: Создание файла Удаление файла Копирование файла ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Просветление в 5 секунд
kumehtar 10.07.2026
Андрей Веретенников выдал фразу недавно: "Вам не обязательно кем-то себя считать"
Эксперимент с картинкой-обложкой на CodinGame
Adler 10.07.2026
Решил на днях провести эксперимент. У меня есть аккаунт на CodinGame, ТОП-3 по РФ среди 2200 участников (в разделе соревнования по программированию ИИ-ботов). Там есть обложка, куда можно влепить. . .
GitDOS: Когда я решил скрестить MS-DOS, GitHub и Claude
MaGz GoLd 08.07.2026
Привет, Киберфорум! Хочу поделиться своим проектом, который, надеюсь, вас заинтересует. GitDOS — это веб-приложение, которое позволяет запускать DOS в браузере с тремя крутыми фичами: диски живут в. . .
Учебный мини "цифровой двойник" = (Сервер = Java + Flask_питон )+(3D = Гугловскаая 4T nvideo + google colab) +( WMS = Odoo на Docker)
anaschu 07.07.2026
Увидел в требованиях к вакансии создателя имитационных моделей связку (REst + Api + WMS + Anylogic + питон + 3D Nvideo), и решил посмотреть, что это такое. Из этого всего я работал более менее. . .
Море в объективе
kumehtar 06.07.2026
Хотел написать много проникновенных слов, но передумал. Оно само - говорит. Кто слышит тот слышит.
Doom для терминала без стрельбы и монстров. 3D Raycasting на ascii.
dcc0 05.07.2026
Попросил нейронную сеть deepai. org написать рейкастинг 3D с библиотекой ncurses для Linux. Чтобы можно было ходить на стрелочки. Чтобы стены были отрисованы символами. Справилась. Первый вариант. . .
Установка статуса документа по условию
Maks 05.07.2026
Алгоритм из решения ниже реализован на нетиповом документе "НарядПутевка" разработанного в КА2. Задача: в табличной части "Материалы" документа при записи автоматически устанавливать статус. . .
Сезонность и суточность закисления почв
anaschu 04.07.2026
200 часов это все равно моловато. Есть ситуации, но нестандартные, когда смена происходит за 5 лет. Но обычно это 50 лет и более. Наверное, закисление почвы происходит сезонно в средней. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru