{"id":3011,"date":"2021-08-03T18:15:48","date_gmt":"2021-08-03T15:15:48","guid":{"rendered":"https:\/\/demensdeum.com\/blog\/?p=3011"},"modified":"2024-12-16T22:32:22","modified_gmt":"2024-12-16T19:32:22","slug":"writing-stuff-in-assembly-for-sega-genesis-5","status":"publish","type":"post","link":"https:\/\/demensdeum.com\/blog\/2021\/08\/03\/writing-stuff-in-assembly-for-sega-genesis-5\/","title":{"rendered":"Writing Assembler for Sega Genesis #5"},"content":{"rendered":"<p>In this post I will describe the process of reading the joystick, changing the sprite position, horizontal flip, Sega Genesis emulator and potentially the console itself.<\/p>\n<p>Reading of presses, processing of \u201cevents\u201d of the Sega joystick occurs according to the following scheme:<\/p>\n<ol>\n<li>Request for combination of bits of pressed buttons<\/li>\n<li>Reading bits of pressed buttons<\/li>\n<li>Processing at the game logic level<\/li>\n<\/ol>\n<p>To move the skeleton sprite we need to store the current position variables.<\/p>\n<h3>RAM<\/h3>\n<p>Game logic variables are stored in RAM, people haven&#8217;t come up with anything better yet. Let&#8217;s declare variable addresses, change the rendering code:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>skeletonYpos = $FF0002 \nframeCounter = $FF0004 \nskeletonHorizontalFlip = $FF0006\n\n    move.w #$0100,skeletonXpos \n    move.w #$0100,skeletonYpos \n    move.w #$0001,skeletonHorizontalFlip \n\nFillSpriteTable: \n    move.l #$70000003,vdp_control_port \n    move.w skeletonYpos,vdp_data_port  \n    move.w #$0F00,vdp_data_port \n    move.w skeletonHorizontalFlip,vdp_data_port \n    move.w skeletonXpos,vdp_data_port \n<\/code><\/pre>\n<\/div>\n<p>As you can see, the address available for work starts at 0xFF0000 and ends at 0xFFFFFF, so we have 64 KB of memory available. Skeleton positions are declared at skeletonXpos, skeletonYpos, horizontal flip at skeletonHorizontalFlip.<\/p>\n<h3>Joypad<\/h3>\n<p>Similar to VDP, joypads are handled via two separate ports &#8211; the control port and the data port, for the first one it&#8217;s 0xA10009 and 0xA10003 respectively. When working with a joypad, there&#8217;s one interesting feature &#8211; first you need to request a combination of buttons for polling, and then, after waiting for the bus update, read the required presses. For the C\/B buttons and the cross, it&#8217;s 0x40, an example below:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>  move.b #$40,joypad_one_control_port; C\/B\/Dpad \n  nop ; bus sync \n  nop ; bus sync \n  move.b joypad_one_data_port,d2 \n  rts \n<\/code><\/pre>\n<\/div>\n<p>The state of the buttons pressed or not pressed will remain in the d2 register, in general, what was requested via the data port will remain. After that, go to the Motorola 68000 register viewer of your favorite emulator, see what the d2 register is equal to depending on the presses. You can find this out in the manual in a smart way, but we don&#8217;t take your word for it. Next, processing the pressed buttons in the d2 register<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>    cmp #$FFFFFF7B,d2; handle left \n    beq MoveLeft  \n    cmp #$FFFFFF77,d2; handle right  \n    beq MoveRight  \n    cmp #$FFFFFF7E,d2; handle up  \n    beq MoveUp  \n    cmp #$FFFFFF7D,d2; handle down  \n    beq MoveDown  \n    rts<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043d\u0443\u0436\u043d\u043e \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0431\u0438\u0442\u044b, \u0430 \u043d\u0435 \u0446\u0435\u043b\u044b\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, \u043d\u043e \u043f\u043e\u043a\u0430 \u0438 \u0442\u0430\u043a \u0441\u043e\u0439\u0434\u0435\u0442. \u0422\u0435\u043f\u0435\u0440\u044c \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u0430\u043c\u043e\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0435 &#8211; \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0432\u0441\u0435\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u043f\u043e 4-\u043c \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f\u043c. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u0435\u043d\u044f\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0432 RAM, \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0443 \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u043a\u0438.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0432\u043b\u0435\u0432\u043e + \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0444\u043b\u0438\u043f\u0430:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>    move.w skeletonXpos,d0 \n    sub.w #1,d0 \n    move.w d0,skeletonXpos \n    move.w #$0801,skeletonHorizontalFlip \n    jmp FillSpriteTable<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0438 \u0441\u0431\u043e\u0440\u043a\u0438, \u0432\u044b \u0443\u0432\u0438\u0434\u0438\u0442\u0435 \u043a\u0430\u043a \u0441\u043a\u0435\u043b\u0435\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u0438 \u043f\u043e\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e \u044d\u043a\u0440\u0430\u043d\u0443, \u043d\u043e \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0431\u044b\u0441\u0442\u0440\u043e, \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0441\u0430\u043c\u043e\u0433\u043e \u0435\u0436\u0430 \u0421\u043e\u043d\u0438\u043a\u0430.<\/p>\n<h3>\u041d\u0435 \u0442\u0430\u043a \u0431\u044b\u0441\u0442\u0440\u043e!<\/h3>\n<p>\u0427\u0442\u043e\u0431\u044b \u0437\u0430\u043c\u0435\u0434\u043b\u0438\u0442\u044c \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430, \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0442\u0435\u0445\u043d\u0438\u043a, \u044f \u0432\u044b\u0431\u0440\u0430\u043b \u0441\u0430\u043c\u0443\u044e \u043f\u0440\u043e\u0441\u0442\u0443\u044e \u0438 \u043d\u0435 \u0437\u0430\u0442\u0440\u0430\u0433\u0438\u0432\u0430\u044e\u0449\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0432\u043d\u0435\u0448\u043d\u0438\u043c\u0438 \u043f\u043e\u0440\u0442\u0430\u043c\u0438 &#8211; \u043f\u043e\u0434\u0441\u0447\u0435\u0442 \u0446\u0438\u0444\u0440\u044b \u0447\u0435\u0440\u0435\u0437 \u0440\u0435\u0433\u0438\u0441\u0442\u0440 \u043f\u043e\u043a\u0430 \u043e\u043d\u0430 \u043d\u0435 \u0441\u0442\u0430\u043d\u0435\u0442 \u0440\u0430\u0432\u043d\u0430 \u043d\u0443\u043b\u044e.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0437\u0430\u043c\u0435\u0434\u043b\u044f\u044e\u0449\u0435\u0433\u043e \u0446\u0438\u043a\u043b\u0430 \u0438 \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>  move.w #512,frameCounter \nWaitFrame: \n  move.w frameCounter,d0 \n  sub.w #1,d0 \n  move.w d0,frameCounter \n  dbra d0,WaitFrame \nGameLoop: \n  jsr ReadJoypad \n  jsr HandleJoypad \n  jmp GameLoop \n<\/code><\/pre>\n<\/div>\n<p>After that, the skeleton runs slower, which is what was required. As far as I know, the most common option for \u201cslowing down\u201d is counting the vertical sync flag, you can count how many times the screen was drawn, thus tying it to a specific fps.<\/p>\n<h3>Links<\/h3>\n<p><a href=\"https:\/\/gitlab.com\/demensdeum\/segagenesisamples\/-\/blob\/main\/8Joypad\/vasm\/main.asm\" target=\"_blank\" rel=\"noopener\">https:\/\/gitlab .com\/demensdeum\/segagenesisamples\/-\/blob\/main\/8Joypad\/vasm\/main.asm <\/a><\/p>\n<h3>Sources<\/h3>\n<p><a href=\"https:\/\/www.chibiakumas.com\/68000\/platform2.php\" target=\"_blank\" rel=\"noopener\">https:\/\/www.chibiakumas.com\/68000\/platform2.php <\/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","protected":false},"excerpt":{"rendered":"<p>In this post I will describe the process of reading the joystick, changing the sprite position, horizontal flip, Sega Genesis emulator and potentially the console itself. Reading of presses, processing of \u201cevents\u201d of the Sega joystick occurs according to the following scheme: Request for combination of bits of pressed buttons Reading bits of pressed buttons<a class=\"more-link\" href=\"https:\/\/demensdeum.com\/blog\/2021\/08\/03\/writing-stuff-in-assembly-for-sega-genesis-5\/\">Continue reading <span class=\"screen-reader-text\">&#8220;Writing Assembler for Sega Genesis #5&#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-3011","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":"en","enabled_languages":["en","ru","zh","de","fr","ja","pt"],"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}}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/demensdeum.com\/blog\/wp-json\/wp\/v2\/posts\/3011","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/demensdeum.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/demensdeum.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/wp-json\/wp\/v2\/comments?post=3011"}],"version-history":[{"count":9,"href":"https:\/\/demensdeum.com\/blog\/wp-json\/wp\/v2\/posts\/3011\/revisions"}],"predecessor-version":[{"id":3894,"href":"https:\/\/demensdeum.com\/blog\/wp-json\/wp\/v2\/posts\/3011\/revisions\/3894"}],"wp:attachment":[{"href":"https:\/\/demensdeum.com\/blog\/wp-json\/wp\/v2\/media?parent=3011"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/wp-json\/wp\/v2\/categories?post=3011"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/wp-json\/wp\/v2\/tags?post=3011"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}