-
Notifications
You must be signed in to change notification settings - Fork 0
/
ModNES status.txt
191 lines (133 loc) · 13.3 KB
/
ModNES status.txt
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
>> 2017-11-27
Después de estar un buen tiempo estancado queriendo implementar CHR RAM y bank switching para soportar mappers, decidí primero implementar un audio, aunque sea básico, para completar la UX del emulador y poder empezar a hacer los primeros MODs para probar el concepto principal de ModNES.
Volví a master y de ahí voy a branchear para implementar audio básico. Pulse, triangle y noise waves.
http://forums.nesdev.com/viewtopic.php?f=3&t=13749&start=15#p162874
>> 2017-09-25
"Averiguar si 3-CNROM usa 16kB con mirror o 32kB PRG, pregunté en nesdev."
- Obviamente la respuesta estaba en el header iNES, si dice 1 PRG banks, es un bank de 16kB y el high es mirror.
http://forums.nesdev.com/viewtopic.php?f=3&t=16478
>> 2017-09-10
Empecé el PRG-ROM switching para poder soportar los mappers 2, 7 y 11.
Agregué a Nes el número de mapper y punteros a los low y high 16kB PRG banks. El puntero a high es fijo y solo se usa para el mapper 2 que switchea sólo la mitad del PRG, y para el mapper 0 en que el high PRG es un mirror del low PRG.
El puntero a low es switcheable y selecciona el banco PRG activo, en mapper 2 apunta al low 16kB y en los mappers 7 y 11 apunta a los 32kB completos del PRG.
Dividí la asignación de punteros de acceso a memory en init_memory_handlers() y set_memory_handlers() ya que ahora los punteros de accesso a PRG-ROM varían según el mapper del ROM que se cargue entonces hay que setearlos cuando se carga el ROM y no al inicio.
Falta:
- Setear el puntero prg_rom_high_bank al último PRG bank leído de la ROM en el caso del mapper 2.
- Escribir el switcheo de los bancos de PRG sea en bancos de 16kB o 32kB.
Averiguar si 3-CNROM usa 16kB con mirror o 32kB PRG, pregunté en nesdev.
Chequear la NesDev wiki y los docs de Disch sobre los mappers 2, 3, 7 y 11 a ver si se me escapó algo de los PRG-ROM que no sabía.
>> 2016-10-08
Sólo le estuve pegando una mirada a estos docs y un poco al código.
El 22 de mayo branchée para implementar CNROM. Quedó un WIP a medio hacer, al final simplemente cargar todos los CHR-ROMs, UnPackearlos y switchearlos porbó no ser tan trivial como me imaginaba.
Me tengo que sentar tranquilo con un café, mirar el estado de todo, quizás reempezar el branch y diseñar una buena solución para esto antes de empezar a codear.
>> 2016-06-11
Implementé un limitador de 60fps precario. clock() no parece tener en cuenta el tiempo transcurrido durante SDL_Delay(), así que tuve que medirlo en milisegundos con SDL_GetTicks()
Debería hacer un contador de frames y que considere skipear frames de ser necesario.
Mediciones de tiempo:
- Main loop < 1 ms
- NES_DoFrame() < 1 ms
- render() ~ 10 ms
Dentro del render, el blitting de nametables tarda unos 7 ms, si solo se rendereara el screen, sería mucho más rápido.
Probablemente usando texturas por hardware se podría incluso hacer más eficiente.
>> 2016-05-30
Implementé un conteo de FPS rudimentario. Las stats al día de hoy son:
~ 100 fps con render común, sin restringir a 60 fps, obvio. Skipear el sprite flip ineficiente no ahorra ni un fps. El cuello de botella tiene que estar en otro lado.
~ 1400 fps sin render, pura emulación Nes. Ejecuta en 2 segundos lo que llevaría 1 minuto en tiempo real de 60 fps.
>> 2016-05-18
Terminé de implementar sprite background priority.
Me costó entender cómo maneja SDL los alpha y los color keys, pero finalmente logré renderear los sprites bajo fondo primero, luego el nametable a screen con el fondo transparente, luego los sprites sobre fondo.
Ahora la nametable sólo muestra los sprites sobre fondo, porque al renderearse los sprites en dos pasadas, la primer pasada bajo fondo quedaría tapada por el dibujado de los tiles de fondo.
También pasa que los sprites rendereados a nametables están con el scroll del final del frame, recortarlos según todos los scrolls midframe sería un trabajo totalmente innecesario.
El rendereado de sprites a nametable es bastante impreciso, pero para fines de debug, funciona. Se podría apagar con algun setting.
Próximo paso: ocultar leftmost 8 pixel column según registros
>> 2016-05-08
Finalmente terminé de implementar el scroll a pantalla partida.
Registro todos los cambios de scroll horizontal durante el frame, siempre en HBlank, y los voy metiendo en un array.
Al final del frame, se puede consultar ese array para saber en qué scanlines se parte la pantalla y cuántos pixeles está cada porción scroleada en X.
El Slalom tiene un código timed que hace un scroll distinto en cada scanline, aún así haberlo hecho con rectángulos de SDL_Blit funciona bastante bien. Hay un problema chico de sincronía que le corre un scanline de cada 10 un poco al costado, pero no muy grave. El tercio superior de la pantalla no scrolea, según Nesdev no usa 8 sprite overflow, así que debe estar esperando otra condición que no se da, pero en el resto de la pantalla la pista parece scrolear bastante bien.
El veredicto es que el scroll está bastante bien implementado por ahora.
Voy a integrar este branch de scroll que estuvo serparado del master por mucho tiempo, de nuevo en master y así seguir con la política de siempre tener un master estable y trabajar en branches y luego integrar a master de nuevo cuando el feature está estable, por lo menos lo suficientemente estable para seguir adelante con otros features importantes.
También cambié el rendereado de sprites directo a pantalla además de renderearlos también en la nametables.
Pasar por nametables complica las cosas, porque hay que andar split-screeneando también los sprites, cosa que en la NES real no sucede, la posición 8bit de los sprites es relativa a la pantalla y no al espacio de 4 nametables.
El rendereado de sprites en nametables probablemente quede sub-óptimo, para cumplir su función de debug y nada más, por ejemplo rendereando todos los sprites con los valores de scroll al terminar el render o quizas no los renderee para nada en las nametables, como hace FCEUX.
También arreglé la title screen del Super Mario Bros! el error era que no estaba implementado el read $2007 del CHR-ROM. Para qué querrá leer el CHR-ROM? no importa. De todas maneras el read y write tendrán que ser implementados para tener CHR-RAM.
Próximos pasos:
- Prioridad sprites - background
- Left tile column clipping
- Mappers, por lo menos los más fáciles 3-CNROM y 11-Color Dreams
- CHR-RAM para mappers 2-UNROM y 7-AOROM
- Luego los mappers masivos MMC1 y MMC3
- Accurate sprite 0 hit
- Factorear el basic SDL render como un mod
- Empezar a diseñar e implementar mods
>> 2016-03-25
Implementé scroll con wraparound en X e Y.
Ahora estoy investigando sobre cómo implementar el mid-frame scroll.
Para los juegos simples y pioneros del mapper NROM, suponía que a lo sumo podían escrolear dos veces midframe, usando el sprite 0 hit y el 8 sprite overflow por scanline.
El Super Mario Bros. usa un scroll para mostrar la GUI arriba.
El Excite Bike usa dos scrolls, para mostrar la pista y abajo la GUI.
El Slalom usa tres scrolls en la intro, para escrolear el título Slalom desde la derecha.
Pero el Kung-fu hace hasta 4 scrolls al principio y 3 durante el juego. Debe usar alguna técnica avanzada de timing, y lo necesita porque
por alguna extraña razón el personaje principal está hecho con tiles de background.
También descubrí que voy a tener que split renderear los sprites.
>> 2016-03-10
Reimplementé el render en SDL, con pallette swaps bliteando de a tiles en vez de a pixel.
Ahora hay ventanas de: Patterns, Nametables y Screen.
Sprites y Pallettes no las hice en SDL, y no las voy a hacer hasta que no las necesite.
Por fin implementé el scroll en 2D, aunque solo en pantalla completa, no split-screen todavía.
Por primera vez ModNES renderea al screen con scroll y le da un aspecto vivo, cada vez más se parece a una NES verdadera.
Al querer hacer el flipping de sprites me di cuenta de que SDL no tiene BlitFlipped() me sorprendió.
Sí tiene para renderers y texturas, seguramente eso lo hace el framework subyacente, e.g. OpenGL.
Tendría que branchear y probar con renderers y texturas a ver si puedo hacer lo mismo que con surfaces. Probablemente no pueda hacer color keying y pallette swap.
El aprendizaje de git con Germinate me sirvió para manejar este proyecto mejor, los conceptos de branching y merging son muy simples pero muy poderosos.
>> 2015-XX-XX En algún punto entre la fecha anterior y la siguiente (lo había puesto en to do)
Holamundeando SDL2.
Descubrí que usando surfaces 8 bpp, si altero los colores de la patleta (no la paleta en sí), antes de blitear, se blitea
correctamente con la paleta deseada.
Voy a implementar cada pattern table como una surface de 256 tiles, o sea 16x16 tiles, 128x128 px
Luego por cada tile que tengo que blitear como fondo o como sprite, ahí le seteo los colores de la paleta y depsués bliteo.
Puedo cachear los tiles vacíos y no blitearlos.
Bliteo en 4 planos: fondo todo del color de fondo, luego sprites por abajo del fondo, luego fondo, luego sprites por arriba de fondo.
Sprites se renderean en orden inverso a sprite number.
(por ahora me cago en sprites bajofondo que tienen mayor prioridad que sprites sobrefondo.)
>> 2015-08-30
Bueno el evento más importante de ModNES fue tan impactante que no escribí nada acá.
Finalmente el emu dibuja fondos y sprites, y agregué input de modo que se pueden jugar algunos juegos.
Acá está la entrada en git del 19/6:
Added Sprites and Screen views.
Added input handling for gamepad #0.
It's Alive!!! this commit is the first minimum viable emulator of ModNES that ever worked, it has minimal screen output and gamepad input so you can actually play some games.
Ahora unifiqué los tres repositorios Cpu6502, Nes y ModNES en uno solo: ModNES.
También dejé Cocoa y me pasé a SDL2, que permite manejar varias ventanas, y además testeando descubrí que con superficies de 8 bpp puedo cambiarles los colores de la paleta efectivamente haciendo palette swaps igual que la NES, o sea que puedo guardar los nametables como surfaces y blitearlas en la pantalla con palette swaps sin necesidad de recalcular los colores pixel por pixel.
>> 2015-05-10 Miércoles (lol, sería 2015-05-13? )
Bueno finalmente arreglé unos addressings erróneos, y le agregué addressing mode a los NOP ilegales, para poder skipearlos y seguir ejecutando.
Ahora Cpu6502 pasa exitosamente Nestest! FUCK YEAH!
Con la excepción de los opcodes ilegales más allá del NOP.
Para los NOP ilegales hay una excepción, al no ejecutar el addressing, los NOP Absolute,X si el direccionamiento cruza un límite de página,
obviamente no estoy agregando el ciclo extra, por lo tanto si se trata de ejecutar un NOP ilegal y se da esta puta casualidad, el conteo de
ciclos de CPU va a estar uno abajo de lo correcto, me cago, no creo que sea demasiado serio.
Esto se podría arreglar ejecutando el addresing para estos NOPs pero creo que no vale la pena ni agacharse por tan poco.
Mejoras a futuro:
Llamar primero al addressing y después a la instrucción, ambos según las correspondientes tablas, en vez de hacer el switch
largo y verbose de CpuStep. (Como hacía antes, con los dos switch y el poderoso goto)
El PC se puede incrementar simplemente basado en el addressing y no hacerlo a mano en cada caso.
>> 2015-05-10 Domingo
Hace unos días finalmente empecé a correr nestest. La primera serie de corridas y posteriormente comparando el log de nestest con el de ModNES me permitió
confirmar que el Cpu6502 estaba corriendo casi perfectamente.
Descubrí algunos bugs seteando el flag de carry, pero salvo eso, todo lo demás parecía estar correctamente implementado.
Luego emulando a la perfección el formato de log de nestest con conteo de ciclos de PPU y con direcciones de addressing, encontré un bug que todavía tengo
que esclarecer.
Después de correr 3300 instrucciones a la perfección, falla `STA ($33),Y` y no escribe en memoria el valor que debería, seguramente el indirect indexed Y tiene
un bug que ya arreglaré.
También debería agregar los addressing modes de los NOP ilegales, más que nada para saber cuántos bytes ocupan esas instrucciones y poder incrementar el pc
en consecuencia, ignorando los efectos colaterales que el estéril addressing de los NOP pudiera causar.
Implementar los NOP ilegales me permite llegar un poco más allá dentro del log de nestest para verificar un poco más la correctitud del Cpu6502
>> 2015-04-23
Hoy corriendo ModNES con Mario Bros. me di cuenta que no había implementado ASL,LSR,ROR,ROL con addressing "Accumulator".
Habría que agregarlos a los tests que corresponda.
Hace varios meses que tenía a ModNES abandonado pensando que Mario Bros. había querido ejecutar una opcode ilegal, lo que suponía uno de dos posibles problemas;
1) Que efectivamente Mario Bros. usara opcodes ilegales, con lo cual probablemente otros juegos Mapper 0 también lo hicieran, y tendría que implementar opcodes ilegales antes de poder correr las primeras pruebas.
2) Que la ejecución se hubiera desfasado de alguna manera y se estuvieran interpretando operandos como opcodes y viceversa, lo cual implicaba volver a testear minuciosamente Cpu6502 para encontrar el error.
Por suerte $0A no era una opcode ilegal sino que era ASL A que no estaba implementada.
Diantres! Seguí la ejecución y ahora sí, quiso ejecutar la instrucción $04 que es ilegal. :(
Sin embargo llega a esa instrucción después de un JMP ($0014), así que puede ser que la indirección sea incorrecta.