{"id":73,"date":"2019-07-26T23:06:19","date_gmt":"2019-07-26T23:06:19","guid":{"rendered":"http:\/\/jaytheham.com\/tink\/?p=73"},"modified":"2019-07-26T23:06:19","modified_gmt":"2019-07-26T23:06:19","slug":"crispy-pixels-in-body-harvest","status":"publish","type":"post","link":"http:\/\/jaytheham.com\/tink\/?p=73","title":{"rendered":"Crispy pixels in Body Harvest"},"content":{"rendered":"\n<p>Body Harvest for the Nintendo 64 is generally regarded as being fun to play, but a bit of a pig to look at, is there anything that can be done to improve that?<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" loading=\"lazy\" width=\"640\" height=\"480\" src=\"http:\/\/jaytheham.com\/tink\/wp-content\/uploads\/2019\/07\/BODY-HARVEST_0001.jpg\" alt=\"\" class=\"wp-image-74\" srcset=\"http:\/\/jaytheham.com\/tink\/wp-content\/uploads\/2019\/07\/BODY-HARVEST_0001.jpg 640w, http:\/\/jaytheham.com\/tink\/wp-content\/uploads\/2019\/07\/BODY-HARVEST_0001-300x225.jpg 300w, http:\/\/jaytheham.com\/tink\/wp-content\/uploads\/2019\/07\/BODY-HARVEST_0001-624x468.jpg 624w\" sizes=\"(max-width: 640px) 100vw, 640px\" \/><figcaption>Body Harvest with no modifications, all screenshots are double-sized from PJ64 with angrylion&#8217;s video plugin.<\/figcaption><\/figure>\n\n\n\n<p>A couple of years back there was a big hullabaloo around disabling Anti-aliasing on N64 games &#8211; removing some of that characteristic blur, and BH certainly has blur. But before changing video interface settings, there&#8217;s actually a bigger problem we can solve. In its low-resolution mode the N64 outputs a video image of 320&#215;240 pixels, but a lot of games don&#8217;t even manage to render this. During gameplay Body Harvest renders at 304&#215;230 and then scales that image up to 320&#215;240 for display, which results in a much blurrier output, what if it were to render at the full output resolution?<\/p>\n\n\n\n<p>At 0x7984 in the NTSC ROM is a function that is called before gameplay starts to set the render resolution:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>addiu\t\tsp, sp, $ffe8\t\t# 00006d84:27bdffe8\t\nsw\t\tra, $0014(sp)\t\t# 00006d88:afbf0014\t\njal\t\t$0000f648\t\t# 00006d8c:0c003d92\tv FNC_0000f648\n\/\/ setVideoInterfaceXSize = 304\naddiu\t\ta0, zero, $0130\t\t# 00006d90:24040130\ta0=$00000130\njal\t\t$0000f67c\t\t# 00006d94:0c003d9f\tv FNC_0000f67c\n\/\/ setVideoInterfaceYSize = 230\naddiu\t\ta0, zero, $00e6\t\t# 00006d98:240400e6\ta0=$000000e6\nlw\t\tra, $0014(sp)\t\t# 00006d9c:8fbf0014\t\naddiu\t\tsp, sp, $0018\t\t# 00006da0:27bd0018\t\njr\t\tra\t\t\t# 00006da4:03e00008\t\nnop\t\t\t\t\t# 00006da8:00000000\t<\/code><\/pre>\n\n\n\n<p>If we change the arguments to the two function calls here to 0x140 and 0xF0 respectively, then the game renders the full output resolution and does no scaling, resulting in this:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" loading=\"lazy\" width=\"640\" height=\"480\" src=\"http:\/\/jaytheham.com\/tink\/wp-content\/uploads\/2019\/07\/Body-Harvest-U-Full320x240.jpg\" alt=\"\" class=\"wp-image-75\" srcset=\"http:\/\/jaytheham.com\/tink\/wp-content\/uploads\/2019\/07\/Body-Harvest-U-Full320x240.jpg 640w, http:\/\/jaytheham.com\/tink\/wp-content\/uploads\/2019\/07\/Body-Harvest-U-Full320x240-300x225.jpg 300w, http:\/\/jaytheham.com\/tink\/wp-content\/uploads\/2019\/07\/Body-Harvest-U-Full320x240-624x468.jpg 624w\" sizes=\"(max-width: 640px) 100vw, 640px\" \/><\/figure>\n\n\n\n<p>That&#8217;s already a noticeable improvement! Presumably the lower resolution was chosen as a performance enhancement, but it&#8217;s a shame it was, the game looks a lot better without any scaling going on.<\/p>\n\n\n\n<p>Can we do more?<br>At 0x10218 in the ROM is this function which sets two Video Interface Special Features, Gamma to off, and Dither to on.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>addiu\t\tsp, sp, $ffe8\t\t# 0000f618:27bdffe8\t\nsw\t\tra, $0014(sp)\t\t# 0000f61c:afbf0014\t\njal\t\t$0000a160\t\t# 0000f620:0c002858\t^ FNC_0000a160\nnop\t\t\t\t\t# 0000f624:00000000\t\njal\t\t$0001f310\t\t# 0000f628:0c007cc4\tv FNC_0001f310\n\/\/ osViSetSpecialFeatures sets OS_VI_GAMMA_OFF\naddiu\t\ta0, zero, $0002\t\t# 0000f62c:24040002\ta0=$00000002\njal\t\t$0001f310\t\t# 0000f630:0c007cc4\tv FNC_0001f310\n\/\/ osViSetSpecialFeatures sets OS_VI_DITHER_FILTER_ON\naddiu\t\ta0, zero, $0040\t\t# 0000f634:24040040\ta0=$00000040\nlw\t\tra, $0014(sp)\t\t# 0000f638:8fbf0014\t\naddiu\t\tsp, sp, $0018\t\t# 0000f63c:27bd0018\t\njr\t\tra\t\t\t# 0000f640:03e00008\t\nnop\t\t\t\t\t# 0000f644:00000000\t<\/code><\/pre>\n\n\n\n<p>If we switch the Dither on flag (0x40) for the off flag (0x80):<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" loading=\"lazy\" width=\"640\" height=\"480\" src=\"http:\/\/jaytheham.com\/tink\/wp-content\/uploads\/2019\/07\/aBody-Harvest-U-Full320x240_DitherFilterOff.jpg\" alt=\"\" class=\"wp-image-76\" srcset=\"http:\/\/jaytheham.com\/tink\/wp-content\/uploads\/2019\/07\/aBody-Harvest-U-Full320x240_DitherFilterOff.jpg 640w, http:\/\/jaytheham.com\/tink\/wp-content\/uploads\/2019\/07\/aBody-Harvest-U-Full320x240_DitherFilterOff-300x225.jpg 300w, http:\/\/jaytheham.com\/tink\/wp-content\/uploads\/2019\/07\/aBody-Harvest-U-Full320x240_DitherFilterOff-624x468.jpg 624w\" sizes=\"(max-width: 640px) 100vw, 640px\" \/><\/figure>\n\n\n\n<p>That makes a big difference, the textures are a lot clearer. Seeing the game run with dither off is a mixed bag though, everything looks quite grainy, like a film, I&#8217;m not sure I prefer it.<\/p>\n\n\n\n<p>Now the Video Mode the game is currently running in is LAN1, where the A stands for Anti-aliasing, in theory we should be able to switch to LPN1, where the P stands for Point-sampling, to achieve even further visual clarity. However changing the call to osViSetMode to LPN1 doesn&#8217;t seem to make any visual difference at all, even on real hardware. It might be that some other value needs changing.<\/p>\n\n\n\n<p>Additionally, as BH doesn&#8217;t make use of the Expansion Pak it should be possible to re-point the framebuffers there and switch to a higher resolution using one of the modes such as HPF1 or HPN1. However when I switch to one of those modes, set the resolutionn to 640&#215;480 and point the (four times larger) framebuffers at some empty RAM, the results are quite odd.<br>Every second frame seems to have what looks something like the Z-buffer drawn half over it, and each vertical half of the frame seems to be drawn over the top of each other as a single frame. I&#8217;m not sure exactly what is going on here.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" loading=\"lazy\" width=\"640\" height=\"480\" src=\"http:\/\/jaytheham.com\/tink\/wp-content\/uploads\/2019\/07\/BODY-HARVEST_0006.jpg\" alt=\"\" class=\"wp-image-77\" srcset=\"http:\/\/jaytheham.com\/tink\/wp-content\/uploads\/2019\/07\/BODY-HARVEST_0006.jpg 640w, http:\/\/jaytheham.com\/tink\/wp-content\/uploads\/2019\/07\/BODY-HARVEST_0006-300x225.jpg 300w, http:\/\/jaytheham.com\/tink\/wp-content\/uploads\/2019\/07\/BODY-HARVEST_0006-624x468.jpg 624w\" sizes=\"(max-width: 640px) 100vw, 640px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" loading=\"lazy\" width=\"640\" height=\"480\" src=\"http:\/\/jaytheham.com\/tink\/wp-content\/uploads\/2019\/07\/BODY-HARVEST_0007.jpg\" alt=\"\" class=\"wp-image-78\" srcset=\"http:\/\/jaytheham.com\/tink\/wp-content\/uploads\/2019\/07\/BODY-HARVEST_0007.jpg 640w, http:\/\/jaytheham.com\/tink\/wp-content\/uploads\/2019\/07\/BODY-HARVEST_0007-300x225.jpg 300w, http:\/\/jaytheham.com\/tink\/wp-content\/uploads\/2019\/07\/BODY-HARVEST_0007-624x468.jpg 624w\" sizes=\"(max-width: 640px) 100vw, 640px\" \/><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>Body Harvest for the Nintendo 64 is generally regarded as being fun to play, but a bit of a pig to look at, is there anything that can be done to improve that? A couple of years back there was a big hullabaloo around disabling Anti-aliasing on N64 games &#8211; removing some of that characteristic [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[3,8,2,5],"_links":{"self":[{"href":"http:\/\/jaytheham.com\/tink\/index.php?rest_route=\/wp\/v2\/posts\/73"}],"collection":[{"href":"http:\/\/jaytheham.com\/tink\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/jaytheham.com\/tink\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/jaytheham.com\/tink\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/jaytheham.com\/tink\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=73"}],"version-history":[{"count":1,"href":"http:\/\/jaytheham.com\/tink\/index.php?rest_route=\/wp\/v2\/posts\/73\/revisions"}],"predecessor-version":[{"id":79,"href":"http:\/\/jaytheham.com\/tink\/index.php?rest_route=\/wp\/v2\/posts\/73\/revisions\/79"}],"wp:attachment":[{"href":"http:\/\/jaytheham.com\/tink\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=73"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/jaytheham.com\/tink\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=73"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/jaytheham.com\/tink\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=73"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}