{"id":2982,"date":"2021-07-29T23:46:10","date_gmt":"2021-07-29T20:46:10","guid":{"rendered":"https:\/\/demensdeum.com\/blog\/?p=2982"},"modified":"2024-12-16T22:32:23","modified_gmt":"2024-12-16T19:32:23","slug":"writing-stuff-in-assembly-for-sega-genesis-3","status":"publish","type":"post","link":"https:\/\/demensdeum.com\/blog\/fr\/2021\/07\/29\/writing-stuff-in-assembly-for-sega-genesis-3\/","title":{"rendered":"\u00c9criture en assemblage pour Sega Genesis #3"},"content":{"rendered":"<p>Dans cet article, je vais d\u00e9crire comment afficher une image \u00e0 partir de tuiles sur l&#8217;\u00e9mulateur Sega Genesis \u00e0 l&#8217;aide de l&#8217;assembleur.<br \/>L&#8217;image de d\u00e9marrage <strong>Demens Deum<\/strong> dans l&#8217;\u00e9mulateur Exodus ressemblera \u00e0 ceci\u00a0:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2983\" src=\"https:\/\/demensdeum.com\/blog\/wp-content\/uploads\/2021\/07\/logo.png\" alt=\"\" width=\"804\" height=\"652\" srcset=\"https:\/\/demensdeum.com\/blog\/wp-content\/uploads\/2021\/07\/logo.png 804w, https:\/\/demensdeum.com\/blog\/wp-content\/uploads\/2021\/07\/logo-300x243.png 300w, https:\/\/demensdeum.com\/blog\/wp-content\/uploads\/2021\/07\/logo-768x623.png 768w\" sizes=\"auto, (max-width: 804px) 100vw, 804px\" \/><\/p>\n<p>Le processus de sortie d&#8217;une image PNG \u00e0 l&#8217;aide de tuiles se fait \u00e9tape par \u00e9tape\u00a0:<\/p>\n<ol>\n<li>R\u00e9duire l&#8217;image \u00e0 la taille de l&#8217;\u00e9cran Shogi<\/li>\n<li>Convertir le format PNG en code de donn\u00e9es d&#8217;assemblage, s\u00e9par\u00e9 en couleurs et en mosa\u00efques<\/li>\n<li>Charger une palette de couleurs dans CRAM<\/li>\n<li>Chargement de tuiles\/motifs dans la VRAM<\/li>\n<li>Chargement des index de tuiles aux adresses du plan\u00a0A\/B dans la VRAM<\/li>\n<li>Vous pouvez r\u00e9duire l&#8217;image \u00e0 la taille de l&#8217;\u00e9cran Shogi \u00e0 l&#8217;aide de votre \u00e9diteur graphique pr\u00e9f\u00e9r\u00e9, tel que Blender.<\/li>\n<\/ol>\n<h3>Conversion PNG<\/h3>\n<p>Pour convertir des images, vous pouvez utiliser l&#8217;outil ImaGenesis ; pour travailler sous wine, les biblioth\u00e8ques Visual Basic 6 sont requises, elles peuvent \u00eatre install\u00e9es \u00e0 l&#8217;aide de winetricks (winetricks vb6run), ou RICHTX32.OCX peut \u00eatre t\u00e9l\u00e9charg\u00e9 depuis Internet et plac\u00e9 dans le dossier de l&#8217;application pour un fonctionnement correct.< \/p><\/p>\n<p>Dans ImaGenesis, vous devez s\u00e9lectionner une couleur 4 bits, exporter les couleurs et les tuiles vers deux fichiers au format assembleur. Ensuite, dans le fichier avec les couleurs, vous devez mettre chaque couleur dans un mot (2 octets), pour cela vous utilisez l&#8217;opcode dc.w.<\/p>\n<p>Par exemple, \u00e9cran de d\u00e9marrage CRAM\u00a0:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>  dc.w $0000 \n  dc.w $0000 \n  dc.w $0222 \n  dc.w $000A \n  dc.w $0226 \n  dc.w $000C \n  dc.w $0220 \n  dc.w $08AA \n  dc.w $0446 \n  dc.w $0EEE \n  dc.w $0244 \n  dc.w $0668 \n  dc.w $0688 \n  dc.w $08AC \n  dc.w $0200 \n  dc.w $0000 \n<\/code><\/pre>\n<\/div>\n<p>Laissez le fichier de tuiles tel quel, il contient d\u00e9j\u00e0 le format correct pour le chargement. Exemple de partie d&#8217;un fichier de tuiles\u00a0:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>\tdc.l\t$11111111\t; Tile #0 \n\tdc.l\t$11111111 \n\tdc.l\t$11111111 \n\tdc.l\t$11111111 \n\tdc.l\t$11111111 \n\tdc.l\t$11111111 \n\tdc.l\t$11111111 \n\tdc.l\t$11111111 \n\tdc.l\t$11111111\t; Tile #1 \n\tdc.l\t$11111111 \n\tdc.l\t$11111111 \n\tdc.l\t$11111111 \n\tdc.l\t$11111111 \n\tdc.l\t$11111111 \n\tdc.l\t$11111111 \n\tdc.l\t$11111111 \n<\/code><\/pre>\n<\/div>\n<p>Comme vous pouvez le voir dans l&#8217;exemple ci-dessus, les tuiles sont une grille 8&#215;8 compos\u00e9e d&#8217;indices de palette de couleurs CRAM.<\/p>\n<h3>Couleurs dans CRAM<\/h3>\n<p>Le chargement dans la CRAM s&#8217;effectue en d\u00e9finissant une commande de chargement de couleur sur une adresse CRAM sp\u00e9cifique dans le port de contr\u00f4le (contr\u00f4le vdp). Le format de commande est d\u00e9crit dans le manuel du logiciel Sega Genesis (1989), j&#8217;ajouterai juste qu&#8217;il suffit d&#8217;ajouter 0x20000 \u00e0 l&#8217;adresse pour passer \u00e0 la couleur suivante.<\/p>\n<p>Ensuite, vous devez charger la couleur dans le port de donn\u00e9es (donn\u00e9es vdp)\u00a0; La fa\u00e7on la plus simple de comprendre le chargement est d&#8217;utiliser l&#8217;exemple ci-dessous\u00a0:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>    lea Colors,a0 ; pointer to Colors label \n    move.l #15,d7; colors counter \nVDPCRAMFillLoopStep: \n    move.l  d0,vdp_control_port ;  \n    move.w  (a0)+,d1; \n    move.w  d1,(vdp_data_port); \n    add.l #$20000,d0 ; increment CRAM address \n    dbra d7,VDPCRAMFillLoopStep \n<\/code><\/pre>\n<\/div>\n<h3>Tuiles dans VRAM<\/h3>\n<p>Vient ensuite le chargement des tuiles\/motifs dans la m\u00e9moire vid\u00e9o VRAM. Pour cela, s\u00e9lectionnez une adresse dans la VRAM, par exemple 0x00000000. Par analogie avec la CRAM, nous contactons le port de contr\u00f4le VDP avec une commande pour \u00e9crire dans la VRAM et l&#8217;adresse de d\u00e9part.<\/p>\n<p>Apr\u00e8s cela, vous pouvez t\u00e9l\u00e9charger des mots longs vers la VRAM\u00a0; par rapport \u00e0 la CRAM, vous n&#8217;avez pas besoin de sp\u00e9cifier l&#8217;adresse pour chaque mot long, car il existe un mode d&#8217;incr\u00e9mentation automatique de la VRAM. Vous pouvez l&#8217;activer en utilisant l&#8217;indicateur de registre VDP 0x0F (dc.b $02)<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>  lea Tiles,a0 \n  move.l #$40200000,vdp_control_port; write to VRAM command \n  move.w #6136,d0 ; (767 tiles * 8 rows) counter \nTilesVRAMLoop: \n  move.l (a0)+,vdp_data_port; \n  dbra d0,TilesVRAMLoop \n<\/code><\/pre>\n<\/div>\n<h3>Index de tuiles dans le plan A\/B<\/h3>\n<p>Maintenant, nous devons remplir l&#8217;\u00e9cran avec des tuiles en fonction de leur index. Pour ce faire, la VRAM est remplie \u00e0 l&#8217;adresse Plane A\/B, qui est inscrite dans les registres VDP (0x02, 0x04). Plus d&#8217;informations sur l&#8217;adressage d\u00e9licat se trouvent dans le manuel de Sega\u00a0; dans mon exemple, l&#8217;adresse VRAM est 0xC000, t\u00e9l\u00e9chargeons les index ici.<\/p>\n<p>Votre image remplira de toute fa\u00e7on l&#8217;espace VRAM hors \u00e9cran, donc apr\u00e8s avoir dessin\u00e9 l&#8217;espace de l&#8217;\u00e9cran, votre moteur de rendu devrait arr\u00eater de dessiner et continuer lorsque le curseur se d\u00e9place vers une nouvelle ligne. Il existe de nombreuses options pour impl\u00e9menter cela\u00a0; j&#8217;ai utilis\u00e9 la version la plus simple de comptage sur deux registres du compteur de largeur d&#8217;image et du compteur de position du curseur.<\/p>\n<p>Exemple de code\u00a0:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>  move.w #0,d0     ; column index \n  move.w #1,d1     ; tile index \n  move.l #$40000003,(vdp_control_port) ; initial drawing location \n  move.l #2500,d7     ; how many tiles to draw (entire screen ~2500) \n\nimageWidth = 31 \nscreenWidth = 64 \n\nFillBackgroundStep: \n  cmp.w\t#imageWidth,d0 \n  ble.w\tFillBackgroundStepFill \nFillBackgroundStep2: \n  cmp.w\t#imageWidth,d0 \n  bgt.w\tFillBackgroundStepSkip \nFillBackgroundStep3: \n  add #1,d0 \n  cmp.w\t#screenWidth,d0 \n  bge.w\tFillBackgroundStepNewRow \nFillBackgroundStep4: \n  dbra d7,FillBackgroundStep    ; loop to next tile \n\nStuck: \n  nop \n  jmp Stuck \n\nFillBackgroundStepNewRow: \n  move.w #0,d0 \n  jmp FillBackgroundStep4 \nFillBackgroundStepFill: \n  move.w d1,(vdp_data_port)    ; copy the pattern to VPD \n  add #1,d1 \n  jmp FillBackgroundStep2 \nFillBackgroundStepSkip: \n  move.w #0,(vdp_data_port)    ; copy the pattern to VPD \n  jmp FillBackgroundStep3 \n<\/code><\/pre>\n<\/div>\n<p>Apr\u00e8s cela, il ne reste plus qu&#8217;\u00e0 assembler la rom \u00e0 l&#8217;aide de vasm, lancer le simulateur et voir l&#8217;image.<\/p>\n<h3>D\u00e9bogage<\/h3>\n<p>Tout ne fonctionnera pas tout de suite, c&#8217;est pourquoi je voudrais recommander les outils d&#8217;\u00e9mulation Exodus suivants\u00a0:<\/p>\n<ol>\n<li>D\u00e9bogueur de processeur M68k<\/li>\n<li>Modification du nombre de cycles du processeur m68k (pour le mode ralenti dans le d\u00e9bogueur)<\/li>\n<li>Visionneuses CRAM, VRAM, plan A\/B<\/li>\n<li>Lisez attentivement la documentation de m68k, les opcodes utilis\u00e9s (tout n&#8217;est pas aussi \u00e9vident qu&#8217;il y para\u00eet \u00e0 premi\u00e8re vue)<\/li>\n<li>Afficher des exemples de code de jeu\/d\u00e9montage sur github<\/li>\n<li>Impl\u00e9menter des sous-programmes d&#8217;exceptions de processeur et les traiter<\/li>\n<\/ol>\n<p>Les pointeurs vers les sous-programmes d&#8217;exception du processeur sont plac\u00e9s dans l&#8217;en-t\u00eate de la rom\u00a0; il existe \u00e9galement un projet sur GitHub avec un d\u00e9bogueur d&#8217;ex\u00e9cution interactif pour Sega, appel\u00e9 genesis-debugger.<\/p>\n<p>Utilisez tous les outils disponibles, ayez un bon codage \u00e0 l&#8217;ancienne et que <strong>Blast Processing<\/strong> soit avec vous\u00a0!<\/p>\n<h3>Liens<\/h3>\n<p><a href=\"https:\/\/gitlab.com\/demensdeum\/segagenesissamples\/-\/tree\/main\/6Image\/vasm\" target=\"_blank\" rel=\"noopener\">https:\/\/gitlab.com\/demensdeum \/segagenesisamples\/-\/tree\/main\/6Image\/vasm<\/a><br \/><a href=\"http:\/\/devster.monkeeh.com\/sega\/imagenesis\/\" target=\"_blank\" rel=\"noopener\">http:\/\/devster.monkeeh.com\/sega\/imagenesis\/<\/a><br \/>\n<a href=\"https:\/\/github.com\/flamewing\/genesis-debugger\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/flamewing\/genesis-debugger<\/a><\/p>\n<h3>Sources<\/h3>\n<p><a href=\"https:\/\/www.chibiakumas.com\/68000\/helloworld.php#LessonH5\" target=\"_blank\" rel=\"noopener\">https:\/\/www.chibiakumas.com\/68000\/helloworld .php#Le\u00e7onH5<\/a><br \/><a href=\"https:\/\/huguesjohnson.com\/programming\/genesis\/tiles-sprites\/\" target=\"_blank\" rel=\"noopener\">https:\/\/huguesjohnson.com\/programming\/genesis\/tiles-sprites\/<\/a><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Dans cet article, je vais d\u00e9crire comment afficher une image \u00e0 partir de tuiles sur l&#8217;\u00e9mulateur Sega Genesis \u00e0 l&#8217;aide de l&#8217;assembleur.L&#8217;image de d\u00e9marrage Demens Deum dans l&#8217;\u00e9mulateur Exodus ressemblera \u00e0 ceci\u00a0: Le processus de sortie d&#8217;une image PNG \u00e0 l&#8217;aide de tuiles se fait \u00e9tape par \u00e9tape\u00a0: R\u00e9duire l&#8217;image \u00e0 la taille de l&#8217;\u00e9cran<a class=\"more-link\" href=\"https:\/\/demensdeum.com\/blog\/fr\/2021\/07\/29\/writing-stuff-in-assembly-for-sega-genesis-3\/\">Continue reading <span class=\"screen-reader-text\">&#8220;\u00c9criture en assemblage pour Sega Genesis #3&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[61,52],"tags":[165,172,174],"class_list":["post-2982","post","type-post","status-publish","format-standard","hentry","category-techie","category-tutorials","tag-asm","tag-roms","tag-vasm","entry"],"translation":{"provider":"WPGlobus","version":"3.0.2","language":"fr","enabled_languages":["en","ru","zh","de","fr","ja","pt","hi"],"languages":{"en":{"title":true,"content":true,"excerpt":false},"ru":{"title":true,"content":true,"excerpt":false},"zh":{"title":true,"content":true,"excerpt":false},"de":{"title":true,"content":true,"excerpt":false},"fr":{"title":true,"content":true,"excerpt":false},"ja":{"title":true,"content":true,"excerpt":false},"pt":{"title":true,"content":true,"excerpt":false},"hi":{"title":false,"content":false,"excerpt":false}}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/demensdeum.com\/blog\/fr\/wp-json\/wp\/v2\/posts\/2982","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/demensdeum.com\/blog\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/demensdeum.com\/blog\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/fr\/wp-json\/wp\/v2\/comments?post=2982"}],"version-history":[{"count":11,"href":"https:\/\/demensdeum.com\/blog\/fr\/wp-json\/wp\/v2\/posts\/2982\/revisions"}],"predecessor-version":[{"id":3896,"href":"https:\/\/demensdeum.com\/blog\/fr\/wp-json\/wp\/v2\/posts\/2982\/revisions\/3896"}],"wp:attachment":[{"href":"https:\/\/demensdeum.com\/blog\/fr\/wp-json\/wp\/v2\/media?parent=2982"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/fr\/wp-json\/wp\/v2\/categories?post=2982"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/fr\/wp-json\/wp\/v2\/tags?post=2982"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}