diff --git a/recompiler/CMakeLists.txt b/recompiler/CMakeLists.txt index 2fc38cd2..f1c0dadd 100644 --- a/recompiler/CMakeLists.txt +++ b/recompiler/CMakeLists.txt @@ -461,6 +461,15 @@ if(BUILD_TESTING) target_compile_options(tas_gpu_flat_blend_${_mode} PRIVATE -${_mode} -UNDEBUG) target_link_libraries(tas_gpu_flat_blend_${_mode} PRIVATE m) add_test(NAME tas_gpu_flat_blend_${_mode} COMMAND tas_gpu_flat_blend_${_mode}) + add_executable(tas_gpu_line_${_mode} + ../runtime/tests/test_source_gpu_line.c ../runtime/src/gpu_sw_renderer.c + ../runtime/src/gpu_vram_dirty.c ../runtime/src/psx_sha256.c) + target_include_directories(tas_gpu_line_${_mode} PRIVATE ../runtime/include) + target_compile_options(tas_gpu_line_${_mode} PRIVATE -${_mode} -UNDEBUG) + target_link_libraries(tas_gpu_line_${_mode} PRIVATE m) + add_test(NAME tas_gpu_line_${_mode} COMMAND ${Python3_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/../runtime/tests/test_source_gpu_line_contracts.py + $) endforeach() endif() diff --git a/runtime/include/source_gpu_command_projection.h b/runtime/include/source_gpu_command_projection.h index 43fe2686..e7ce0c2a 100644 --- a/runtime/include/source_gpu_command_projection.h +++ b/runtime/include/source_gpu_command_projection.h @@ -11,6 +11,7 @@ * explicitly qualified source GPU service event; reads do not advance it. * Current scope: NOP/cache-clear, drawing environment, A0/C0 transfers,02 fills,80 copies, variable rectangles, * observed untextured/textured polygons, including general opaque flat quads, + * and flat two-vertex lines (0x40-0x47), * with inclusive clipping. Vertex and drawing offset are independently signed11-bit. Their sum stays * within[-2048,2046]; source signed clipping and raw interpolation are separate. * Clipping stays inside the admitted VRAM draw area. @@ -63,11 +64,15 @@ static inline int source_gpu_polygon_supported(unsigned opcode) { static inline unsigned source_gpu_polygon_setup(unsigned opcode) { return opcode&4 ? (opcode&0x10 ? 450:180) : (opcode&0x10 ? 288:0); } +static inline int source_gpu_line_supported(unsigned command) { + return command>=0x40 && command<=0x47; /* Two-vertex, flat-color lines. */ +} static inline int source_gpu_block_supported(unsigned command) { return command==2 || command==0x80 || command==0x60 || command==0x62 || command==0x64 || command==0x65 || command==0x66; } static inline unsigned source_gpu_command_length(uint32_t word) { unsigned command=word>>24; + if(source_gpu_line_supported(command))return 3; if(source_gpu_block_supported(command))return command==0x80 || command==0x64 || command==0x65 || command==0x66?4:3; if(source_gpu_polygon_supported(command))return 1+3*source_gpu_polygon_stride(command)-!!(command&0x10); return command==0xa0 || command==0xc0 ? 3u : 1u; @@ -150,6 +155,17 @@ static inline int source_gpu_command_block_cost(const SourceGPUCommandProjection return cost; } +/* gpu_line.cpp charges setup and the unclipped major-axis length. Degenerate + * lines still draw one pixel; oversize lines pay setup without raster work. */ +static inline int source_gpu_command_line_cost(const SourceGPUCommandProjection *s,const uint32_t *words) { + if(s->clip_y0>511 || s->clip_y1>511 || + ((s->display_mode&0x24)==0x24 && !(s->draw_mode&0x400) && !s->field_valid))return -1; + int dx=source_gpu_command_coord(words[2],0)-source_gpu_command_coord(words[1],0); + int dy=source_gpu_command_coord(words[2],16)-source_gpu_command_coord(words[1],16); + if(dx<0)dx=-dx;if(dy<0)dy=-dy; + return 16+((dx>=1024 || dy>=512)?0:2*(dx>dy?dx:dy)); +} + static inline int source_gpu_command_process(SourceGPUCommandProjection *s) { s->dispatch.kind=SOURCE_GPU_DISPATCH_NONE; if(s->error) return 0; @@ -177,6 +193,14 @@ static inline int source_gpu_command_process(SourceGPUCommandProjection *s) { } unsigned command=s->queue[0]>>24; + if(source_gpu_line_supported(command)) { + if(s->budget<0 || s->count<3)return 1; + int cost=source_gpu_command_line_cost(s,s->queue); + if(cost<0){s->error=SOURCE_GPU_COMMAND_UNSUPPORTED;return 0;} + s->dispatch.kind=SOURCE_GPU_DISPATCH_COMMAND;s->dispatch.count=3; + for(unsigned i=0;i<3;i++)s->dispatch.words[i]=source_gpu_command_pop(s); + s->budget-=2+cost;return 1; + } if(source_gpu_block_supported(command)) { unsigned n=source_gpu_command_length(s->queue[0]); if(s->budget<0 || s->countwords[0]); } else if(event->kind==SOURCE_GPU_DISPATCH_COMMAND) { unsigned opcode=event->words[0]>>24; - if(source_gpu_block_supported(opcode)) { + if(source_gpu_block_supported(opcode) || source_gpu_line_supported(opcode)) { gp0_opcode_count[opcode]++; if(opcode==2)gp0_fill_count++;else if(opcode==0x80)gp0_copy_count++;else gp0_draw_count++; gp0_ring_record(gp0_cmd_buf,event->count); diff --git a/runtime/src/gpu_sw_renderer.c b/runtime/src/gpu_sw_renderer.c index 4ab9e07e..2a77f842 100644 --- a/runtime/src/gpu_sw_renderer.c +++ b/runtime/src/gpu_sw_renderer.c @@ -404,6 +404,32 @@ int sw_draw_source_block(const SourceGPUBlock *block,int *extra_work) { *extra_work=0; if(g_hr || g_wide_cur || g_precise_valid || g_perspective_valid)return 0; const uint32_t *words=block->words;unsigned opcode=words[0]>>24; + if(opcode>=0x40 && opcode<=0x47) { + int dx=(int)((words[2]&2047u)^1024u)-(int)((words[1]&2047u)^1024u); + int dy=(int)(((words[2]>>16)&2047u)^1024u)-(int)(((words[1]>>16)&2047u)^1024u); + int ax=abs(dx),ay=abs(dy),length=ax>ay?ax:ay; + if(ax>=1024 || ay>=512)return 1; + int x=block->x,y=block->y; + if(dx<=0 && length){x+=dx;y+=dy;dx=-dx;dy=-dy;} + /* Source line interpolation uses 32 fractional bits, rounds the step + * away from zero, and biases half-pixel ties by 1024 fractional units. */ + int64_t sx=(int64_t)dx*4294967296LL,sy=(int64_t)dy*4294967296LL; + if(length) { + sx=(sx+(sx<0?1-length:sx>0?length-1:0))/length; + sy=(sy+(sy<0?1-length:sy>0?length-1:0))/length; + } + uint64_t fx=((uint64_t)(int64_t)x<<32)+2147483648ULL-1024; + uint64_t fy=((uint64_t)(int64_t)y<<32)+2147483648ULL-(sy<0?1024:0); + SourceTriangleColors c={0};c.dither=!!(block->draw_mode&512u); + for(unsigned channel=0;channel<3;channel++)c.base[channel]=((words[0]>>(8*channel))&255u)*4096u; + for(int i=0;i<=length;i++,fx+=(uint64_t)sx,fy+=(uint64_t)sy) { + int px=(int)((fx>>32)&2047u),py=(int)((fy>>32)&2047u); + if(pxclip_left || px>block->clip_right || pyclip_top || py>block->clip_bottom)continue; + if(block->interlace && ((unsigned)py&1u)==block->skip_field)continue; + source_triangle_span(&c,py,px,1,px); + } + return 1; + } if(opcode==2) { unsigned x0=words[1]&1008u,y0=(words[1]>>16)&511u; unsigned width=((words[2]&1023u)+15u)&~15u,height=(words[2]>>16)&511u; diff --git a/runtime/tests/source_gpu_line_fixtures.json b/runtime/tests/source_gpu_line_fixtures.json new file mode 100644 index 00000000..59c60842 --- /dev/null +++ b/runtime/tests/source_gpu_line_fixtures.json @@ -0,0 +1,4369 @@ +{ + "scope": "Generate authored line fixtures using unedited Nymashock source functions.\n\nBuilds extracted reference functions only in the supplied private output folder.\nThis is a component oracle, not an unmodified-core or full-replay qualification.\n", + "source_files": [ + { + "path": "D:\\psxrecomp\\campaign-runs\\tas-accuracy-20260909-r1\\oracle\\BizHawk-source-2.9.1\\waterbox\\nyma\\mednafen\\src\\psx\\gpu_line.cpp", + "sha256": "985e223da66ed1bc899cf544b3d21d2b7e5e7d4a37c48fa67bfc5517f40fcab3" + }, + { + "path": "D:\\psxrecomp\\campaign-runs\\tas-accuracy-20260909-r1\\oracle\\BizHawk-source-2.9.1\\waterbox\\nyma\\mednafen\\src\\psx\\gpu_common.inc", + "sha256": "0f34603e57a2544b1d7c25abafb013dc0e6d829d4a013b55b1e0bb68c6a95282" + } + ], + "driver_sha256": "63a251a5c0aa9ad49ec85e51b1e06ec3a81e2f520ce7a4081e43dea86cac8e67", + "extracted_harness_sha256": "4c8ca9f05becb15a8e3f92927ebdf3b3e938be28153f1d0dc76966e466c12f66", + "cases": [ + { + "input": [ + 64, + 65280, + 84, + 162, + 84, + 162, + 0, + 240, + 512, + 0, + 0, + 0 + ], + "expected": "18 c8bed652e2d2933af14fa271abfc4a5ac379afadd590bad720639967194c099e" + }, + { + "input": [ + 65, + 14914603, + 0, + 0, + 0, + 0, + 0, + 0, + 512, + 0, + 0, + 0 + ], + "expected": "18 f10b513b322bd6291b596a3e2cd480e8670eb2d8754c923932a24a24ce279175" + }, + { + "input": [ + 66, + 16777215, + 4, + 4, + 12, + 4, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "expected": "34 3fc87f8a0dafdeafe46ab0e565bdd5e9e75f00fc1fe0a60c9506fb48c2af69de" + }, + { + "input": [ + 67, + 0, + 4, + 4, + 4, + 12, + 0, + 0, + 512, + 0, + 0, + 4 + ], + "expected": "34 b5544bacd5d731243c48b8a9255e62c5370d0ddc3d490a6c5cd06b68ea37dead" + }, + { + "input": [ + 68, + 65280, + 4, + 4, + 12, + 8, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "expected": "34 9de865391c5865a1d492db51e488356c34b81b4d7c404503ffc9fcbb368f86a4" + }, + { + "input": [ + 69, + 14914603, + 12, + 8, + 4, + 4, + 0, + 0, + 512, + 0, + 0, + 0 + ], + "expected": "34 4de40c5f4eac31a448c2a9cd917836fc85214eca5448f36512d1b72dcc7633df" + }, + { + "input": [ + 70, + 16777215, + 4, + 12, + 12, + 4, + 0, + 0, + 0, + 0, + 0, + 4 + ], + "expected": "34 4e896d260d17c038a9013959c8a43d6301532889b7776ec96afb1343a25c644b" + }, + { + "input": [ + 71, + 0, + -1, + -1, + 8, + 8, + 0, + 0, + 1536, + 0, + 0, + 0 + ], + "expected": "36 3ba6560295d599eba4b5699da54d8afc30a203ba320a4dc30aa9012a36c02c2e" + }, + { + "input": [ + 64, + 65280, + 0, + 0, + 1023, + 511, + 0, + 0, + 32, + 0, + 0, + 0 + ], + "expected": "2064 6a2ba9a5d6e287189f4b3c2cc6de81db5276edf7e638d0c9d11d8a0763b2aafc" + }, + { + "input": [ + 65, + 14914603, + 0, + 0, + 1024, + 0, + 0, + 0, + 544, + 0, + 0, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 66, + 16777215, + 0, + 0, + 0, + 512, + 0, + 0, + 32, + 0, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 67, + 0, + 1023, + 511, + 1023, + 511, + 0, + 0, + 544, + 0, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + -1024, + -1024, + -1024, + -1024, + 0, + 0, + 32, + 0, + 0, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 69, + 14914603, + 84, + 162, + 84, + 162, + 0, + 0, + 544, + 0, + 0, + 0 + ], + "expected": "18 6f558fc19486442ba769870a7992500533b258387d53363dd3195f92eb39d344" + }, + { + "input": [ + 70, + 16777215, + 0, + 0, + 0, + 0, + 0, + 0, + 1056, + 0, + 0, + 0 + ], + "expected": "18 322e1fd4eea0a88f3d7596c930b483aaa2ec9a010d34191d13764cd85ff13925" + }, + { + "input": [ + 71, + 0, + 4, + 4, + 12, + 4, + 0, + 0, + 544, + 0, + 0, + 4 + ], + "expected": "34 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + 4, + 4, + 4, + 12, + 0, + 0, + 64, + 0, + 0, + 0 + ], + "expected": "34 8889cdd708edf4c2bef9e125d193db32a312329338a4c8664778178bd83b6393" + }, + { + "input": [ + 65, + 14914603, + 4, + 4, + 12, + 8, + 0, + 0, + 576, + 0, + 0, + 0 + ], + "expected": "34 4de40c5f4eac31a448c2a9cd917836fc85214eca5448f36512d1b72dcc7633df" + }, + { + "input": [ + 66, + 16777215, + 12, + 8, + 4, + 4, + 0, + 0, + 64, + 0, + 0, + 4 + ], + "expected": "34 6cf2ce44bb7009fb8c01b9c76c4f9a7961c8937c389eaf9b5238a8a6eb72c48b" + }, + { + "input": [ + 67, + 0, + 4, + 12, + 12, + 4, + 0, + 0, + 576, + 0, + 0, + 0 + ], + "expected": "34 43aa26d93f6d81e174741102a5a6863534c558186ea22275f9c2ddd0f3647014" + }, + { + "input": [ + 68, + 65280, + -1, + -1, + 8, + 8, + 0, + 0, + 64, + 0, + 0, + 0 + ], + "expected": "36 a9d73b4ea7c766bfb3fb379852d502e437b61d37675e0c14a6d9afe0e52c99c5" + }, + { + "input": [ + 69, + 14914603, + 0, + 0, + 1023, + 511, + 0, + 0, + 1600, + 0, + 0, + 4 + ], + "expected": "2064 a39d5a94896d18ce22ae3ed982d9e1582bda2ac886015b638c20e4a4bb121b40" + }, + { + "input": [ + 70, + 16777215, + 0, + 0, + 1024, + 0, + 0, + 0, + 64, + 0, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 71, + 0, + 0, + 0, + 0, + 512, + 0, + 0, + 576, + 0, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + 1023, + 511, + 1023, + 511, + 0, + 0, + 96, + 0, + 0, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + -1024, + -1024, + -1024, + -1024, + 0, + 0, + 608, + 0, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 66, + 16777215, + 84, + 162, + 84, + 162, + 0, + 0, + 96, + 0, + 0, + 0 + ], + "expected": "18 b9b5e8465fb517e67c58bcf2b6a8d5a90890e7b64cc1f6a0722fbcf7e98b5771" + }, + { + "input": [ + 67, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 608, + 0, + 0, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + 4, + 4, + 12, + 4, + 0, + 0, + 1120, + 0, + 0, + 0 + ], + "expected": "34 1fade958bd0e023e91b8e913a13d4a2a25077dee47fe55d06fc5c30266e8d3d9" + }, + { + "input": [ + 69, + 14914603, + 4, + 4, + 4, + 12, + 0, + 0, + 608, + 0, + 0, + 0 + ], + "expected": "34 542839519010ea8794f89c70781cfed8524a3d04ce43e22a8d821cf9d336a108" + }, + { + "input": [ + 70, + 16777215, + 4, + 4, + 12, + 8, + 0, + 0, + 96, + 0, + 0, + 4 + ], + "expected": "34 0a59339a23310204b0d032611194cacf47aea21ab1bf0bf5fc0513356e1d2731" + }, + { + "input": [ + 71, + 0, + 12, + 8, + 4, + 4, + 0, + 0, + 608, + 0, + 0, + 0 + ], + "expected": "34 5eb77f314356ecf8cbb308da45493c65e468d1cc95fbc5f56f21af8fad628bf5" + }, + { + "input": [ + 64, + 65280, + 4, + 12, + 12, + 4, + 0, + 0, + 0, + 1, + 0, + 0 + ], + "expected": "34 f626771dc16948b43a0a81ff1eed3d5a972799d852e883e4f78a520b85a3591a" + }, + { + "input": [ + 65, + 14914603, + -1, + -1, + 8, + 8, + 0, + 0, + 512, + 1, + 0, + 4 + ], + "expected": "36 b3f3a0111cd3596e1bffa68722517399441049ff1466be745662594e40e4140c" + }, + { + "input": [ + 66, + 16777215, + 0, + 0, + 1023, + 511, + 0, + 0, + 0, + 1, + 0, + 0 + ], + "expected": "2064 3a1ea626a531311acf8cdcc073ab1f514fae1d60e59cb5ccff7240a3865620e7" + }, + { + "input": [ + 67, + 0, + 0, + 0, + 1024, + 0, + 0, + 0, + 1536, + 1, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + 0, + 0, + 0, + 512, + 0, + 0, + 0, + 1, + 0, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 69, + 14914603, + 1023, + 511, + 1023, + 511, + 0, + 0, + 512, + 1, + 0, + 0 + ], + "expected": "18 0f58977421f034d4f787546cce9728e93e85754fff0b62668240a4dbd556ca72" + }, + { + "input": [ + 70, + 16777215, + -1024, + -1024, + -1024, + -1024, + 0, + 0, + 0, + 1, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 71, + 0, + 84, + 162, + 84, + 162, + 0, + 0, + 512, + 1, + 0, + 4 + ], + "expected": "18 77849fea8689e64950e8bbc55ec0452ae8c1905a59baf64127ebb2b42452c016" + }, + { + "input": [ + 64, + 65280, + 0, + 0, + 0, + 0, + 0, + 0, + 32, + 1, + 0, + 0 + ], + "expected": "18 2dfc34e4553dd7d022cbf2112687415a1854edc504ce02cca679e2d631ba36e9" + }, + { + "input": [ + 65, + 14914603, + 4, + 4, + 12, + 4, + 0, + 0, + 544, + 1, + 0, + 0 + ], + "expected": "34 de901b4e90629c905a0c99197316378169d1f45f5a8bd0ddccdb0f428a066a6a" + }, + { + "input": [ + 66, + 16777215, + 4, + 4, + 4, + 12, + 0, + 0, + 1056, + 1, + 0, + 4 + ], + "expected": "34 14826666b7351240affa5c1535b046c082b9f7262217cf26133eee661b58ce37" + }, + { + "input": [ + 67, + 0, + 4, + 4, + 12, + 8, + 0, + 0, + 544, + 1, + 0, + 0 + ], + "expected": "34 9d4870a30f6e4ed10ce346d256ca7028a11fd23ab313e5dbd9e577472380ebf2" + }, + { + "input": [ + 68, + 65280, + 12, + 8, + 4, + 4, + 0, + 0, + 32, + 1, + 0, + 0 + ], + "expected": "34 5448f330eaaf6d70aff1d38d1261e1eaf4eec1f644654f600f8b4052e4a3e381" + }, + { + "input": [ + 69, + 14914603, + 4, + 12, + 12, + 4, + 0, + 0, + 544, + 1, + 0, + 4 + ], + "expected": "34 6c8f64aa0f6b687b6e8b145d587229dadbd5c611d87c384db6685e61726faf4b" + }, + { + "input": [ + 70, + 16777215, + -1, + -1, + 8, + 8, + 0, + 0, + 32, + 1, + 0, + 0 + ], + "expected": "36 bcf6ea03ca74296b5ba3c892dee391eb6d65ee20545b64c7534ae1edbc3e71ee" + }, + { + "input": [ + 71, + 0, + 0, + 0, + 1023, + 511, + 0, + 0, + 544, + 1, + 0, + 0 + ], + "expected": "2064 b950b36bfc4e483edef3e694db9642e5a7e31e78c78b496e693a9c83e13e86dc" + }, + { + "input": [ + 64, + 65280, + 0, + 0, + 1024, + 0, + 0, + 0, + 64, + 1, + 0, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + 0, + 0, + 0, + 512, + 0, + 0, + 1600, + 1, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 66, + 16777215, + 1023, + 511, + 1023, + 511, + 0, + 0, + 64, + 1, + 0, + 0 + ], + "expected": "18 31767eeea8624fd6aae6c102aa30691caea0b3b92aa28182e7b65f54d812ad19" + }, + { + "input": [ + 67, + 0, + -1024, + -1024, + -1024, + -1024, + 0, + 0, + 576, + 1, + 0, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + 84, + 162, + 84, + 162, + 0, + 0, + 64, + 1, + 0, + 0 + ], + "expected": "18 d05966c72c91aaa9ccefb6867daef41cb7617882965786c46fa97953d3c11d66" + }, + { + "input": [ + 69, + 14914603, + 0, + 0, + 0, + 0, + 0, + 0, + 576, + 1, + 0, + 0 + ], + "expected": "18 7dca62ac32e53e92489ed5087cd389359c7762228bf060e16570d124d0d40840" + }, + { + "input": [ + 70, + 16777215, + 4, + 4, + 12, + 4, + 0, + 0, + 64, + 1, + 0, + 4 + ], + "expected": "34 6d459c7d3f57ca7516e1854c6ede47e82bb7db8708ff995c965caa0bc5e644bb" + }, + { + "input": [ + 71, + 0, + 4, + 4, + 4, + 12, + 0, + 0, + 576, + 1, + 0, + 0 + ], + "expected": "34 d8517875b63dc54fee710ede2c5c2a1ac1f4fb251419dbb87851610ca918b2c8" + }, + { + "input": [ + 64, + 65280, + 4, + 4, + 12, + 8, + 0, + 0, + 1120, + 1, + 0, + 0 + ], + "expected": "34 5448f330eaaf6d70aff1d38d1261e1eaf4eec1f644654f600f8b4052e4a3e381" + }, + { + "input": [ + 65, + 14914603, + 12, + 8, + 4, + 4, + 0, + 0, + 608, + 1, + 0, + 4 + ], + "expected": "34 366f056f23447a9fd56cfed99c1eda4d73faef672f9d0a0acf1cecce91b1aa43" + }, + { + "input": [ + 66, + 16777215, + 4, + 12, + 12, + 4, + 0, + 0, + 96, + 1, + 0, + 0 + ], + "expected": "34 b5ec6cf4da3ef9290c4519b0b34692147c89fdc0200d53dbd2428b29c21110d0" + }, + { + "input": [ + 67, + 0, + -1, + -1, + 8, + 8, + 0, + 0, + 608, + 1, + 0, + 0 + ], + "expected": "36 31aa82897db9c45f2b45226d89d6c00a56225445c77e53421eda0f51071ca220" + }, + { + "input": [ + 68, + 65280, + 0, + 0, + 1023, + 511, + 0, + 0, + 96, + 1, + 0, + 4 + ], + "expected": "2064 ab13c8202cc0e3b351dab03721d90572a7ddda0b3bad8022e73e0b49707678d8" + }, + { + "input": [ + 69, + 14914603, + 0, + 0, + 1024, + 0, + 0, + 0, + 608, + 1, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 70, + 16777215, + 0, + 0, + 0, + 512, + 0, + 0, + 96, + 1, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 71, + 0, + 1023, + 511, + 1023, + 511, + 0, + 0, + 1632, + 1, + 0, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + -1024, + -1024, + -1024, + -1024, + 0, + 0, + 0, + 2, + 1, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + 84, + 162, + 84, + 162, + 0, + 0, + 512, + 2, + 1, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 66, + 16777215, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2, + 1, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 67, + 0, + 4, + 4, + 12, + 4, + 0, + 0, + 512, + 2, + 1, + 0 + ], + "expected": "34 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + 4, + 4, + 4, + 12, + 0, + 0, + 0, + 2, + 1, + 0 + ], + "expected": "34 47d542be81e31fc7adbf6dea3dfcfab0ca4718eb00f902e0de825e4fd8049628" + }, + { + "input": [ + 69, + 14914603, + 4, + 4, + 12, + 8, + 0, + 0, + 512, + 2, + 1, + 4 + ], + "expected": "34 1aec621cf6437db223ca9f4f83c9803da5071ab07c5b994a59077fe522880602" + }, + { + "input": [ + 70, + 16777215, + 12, + 8, + 4, + 4, + 0, + 0, + 1024, + 2, + 1, + 0 + ], + "expected": "34 e1332e825730d79f69eacbf66c925b61d0f84854582e09c7073ddba81c1ed9e6" + }, + { + "input": [ + 71, + 0, + 4, + 12, + 12, + 4, + 0, + 0, + 512, + 2, + 1, + 0 + ], + "expected": "34 bf4fdfeabb3aa15c870c45469498bf0ebf527bfbd358aecf3b692c7ac1339afd" + }, + { + "input": [ + 64, + 65280, + -1, + -1, + 8, + 8, + 0, + 0, + 32, + 2, + 1, + 4 + ], + "expected": "36 bf9ff41d080cc1bbb4fbe7c5a32c1608e3d839c7548b9c17dbd78a81bbeef7a8" + }, + { + "input": [ + 65, + 14914603, + 0, + 0, + 1023, + 511, + 0, + 0, + 544, + 2, + 1, + 0 + ], + "expected": "2064 683598ecfb685d57f44315b3b861108d03fcee79ee0d8374383b6367d1af8fa5" + }, + { + "input": [ + 66, + 16777215, + 0, + 0, + 1024, + 0, + 0, + 0, + 32, + 2, + 1, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 67, + 0, + 0, + 0, + 0, + 512, + 0, + 0, + 544, + 2, + 1, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + 1023, + 511, + 1023, + 511, + 0, + 0, + 32, + 2, + 1, + 0 + ], + "expected": "18 db687b2e323039696dcaf796a7eddbe4aadf9a852225ddd750dec2278be31f61" + }, + { + "input": [ + 69, + 14914603, + -1024, + -1024, + -1024, + -1024, + 0, + 0, + 1568, + 2, + 1, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 70, + 16777215, + 84, + 162, + 84, + 162, + 0, + 0, + 32, + 2, + 1, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 71, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 544, + 2, + 1, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + 4, + 4, + 12, + 4, + 0, + 0, + 64, + 2, + 1, + 0 + ], + "expected": "34 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + 4, + 4, + 4, + 12, + 0, + 0, + 576, + 2, + 1, + 4 + ], + "expected": "34 272216b0476e3ec8ce6666d5225e0929aac48d2e555c4566176e70c0b476173a" + }, + { + "input": [ + 66, + 16777215, + 4, + 4, + 12, + 8, + 0, + 0, + 64, + 2, + 1, + 0 + ], + "expected": "34 4b2499431c6ee8f3bab548ec93f4811a90f571d939488fb93f261d359448e893" + }, + { + "input": [ + 67, + 0, + 12, + 8, + 4, + 4, + 0, + 0, + 576, + 2, + 1, + 0 + ], + "expected": "34 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + 4, + 12, + 12, + 4, + 0, + 0, + 1088, + 2, + 1, + 4 + ], + "expected": "34 79d2b90f900e22dce747b9628fe4ce0b2372342fd24f29cd56332f6f3ff535a4" + }, + { + "input": [ + 69, + 14914603, + -1, + -1, + 8, + 8, + 0, + 0, + 576, + 2, + 1, + 0 + ], + "expected": "36 07972ec5fd6fb181154fd60842ecbf17f87a2e66db8dfb5e4502cf896986cac7" + }, + { + "input": [ + 70, + 16777215, + 0, + 0, + 1023, + 511, + 0, + 0, + 64, + 2, + 1, + 0 + ], + "expected": "2064 9068e1dbfa2b2380620daeaea63ba992bb3145b2bd337dcaf7b4e13ce7ed6fb4" + }, + { + "input": [ + 71, + 0, + 0, + 0, + 1024, + 0, + 0, + 0, + 576, + 2, + 1, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + 0, + 0, + 0, + 512, + 0, + 0, + 96, + 2, + 1, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + 1023, + 511, + 1023, + 511, + 0, + 0, + 608, + 2, + 1, + 0 + ], + "expected": "18 b8308376ab411056e244ecad70b16754c4e0e034da7465d71aba60654a5ed39e" + }, + { + "input": [ + 66, + 16777215, + -1024, + -1024, + -1024, + -1024, + 0, + 0, + 96, + 2, + 1, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 67, + 0, + 84, + 162, + 84, + 162, + 0, + 0, + 1632, + 2, + 1, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + 0, + 0, + 0, + 0, + 0, + 0, + 96, + 2, + 1, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 69, + 14914603, + 4, + 4, + 12, + 4, + 0, + 0, + 608, + 2, + 1, + 4 + ], + "expected": "34 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 70, + 16777215, + 4, + 4, + 4, + 12, + 0, + 0, + 96, + 2, + 1, + 0 + ], + "expected": "34 bf87c9bc411d09d01bf5b0c5efd4c4ceb47657900a77d504c874b407626841ca" + }, + { + "input": [ + 71, + 0, + 4, + 4, + 12, + 8, + 0, + 0, + 608, + 2, + 1, + 0 + ], + "expected": "34 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + 12, + 8, + 4, + 4, + 0, + 0, + 0, + 3, + 1, + 4 + ], + "expected": "34 7f4682796db8222ee1cbf5c51ccab522a1d255621f294f0f238759cc80dc15c4" + }, + { + "input": [ + 65, + 14914603, + 4, + 12, + 12, + 4, + 0, + 0, + 512, + 3, + 1, + 0 + ], + "expected": "34 03e3da5bf8691fbe376d11415b8c45c0e341018a3f29f9d92eaea30d7bcad439" + }, + { + "input": [ + 66, + 16777215, + -1, + -1, + 8, + 8, + 0, + 0, + 1024, + 3, + 1, + 0 + ], + "expected": "36 181347e39cf90428d49cc2e381a9f1a7a04a04a6d7da45c03b0508cf1feb7fa0" + }, + { + "input": [ + 67, + 0, + 0, + 0, + 1023, + 511, + 0, + 0, + 512, + 3, + 1, + 4 + ], + "expected": "2064 3933e3d34864006cb0b008448c8df890497082db9503759977f3fe0c85f1c926" + }, + { + "input": [ + 68, + 65280, + 0, + 0, + 1024, + 0, + 0, + 0, + 0, + 3, + 1, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 69, + 14914603, + 0, + 0, + 0, + 512, + 0, + 0, + 512, + 3, + 1, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 70, + 16777215, + 1023, + 511, + 1023, + 511, + 0, + 0, + 0, + 3, + 1, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 71, + 0, + -1024, + -1024, + -1024, + -1024, + 0, + 0, + 512, + 3, + 1, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + 861, + -592, + 46, + 1007, + -1, + -1024, + 32, + 3, + 1, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + -771, + 828, + 830, + 945, + -1024, + -1024, + 1568, + 3, + 1, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 66, + 16777215, + 197, + 514, + 693, + -232, + -1024, + -1, + 32, + 3, + 1, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 67, + 0, + 877, + 459, + 517, + 443, + -1, + 240, + 544, + 3, + 1, + 0 + ], + "expected": "738 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + -906, + 564, + 896, + -16, + 1023, + -1, + 32, + 3, + 1, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 69, + 14914603, + 548, + -845, + 596, + 523, + -1, + -1024, + 544, + 3, + 1, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 70, + 16777215, + 790, + -330, + -448, + 44, + 1023, + 0, + 32, + 3, + 1, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 71, + 0, + -555, + 888, + 889, + 851, + 0, + 1023, + 544, + 3, + 1, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + 436, + 630, + 797, + -1010, + 0, + -1024, + 1088, + 3, + 1, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + -647, + 56, + -495, + 868, + -1, + 240, + 576, + 3, + 1, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 66, + 16777215, + 403, + -28, + 472, + -591, + 1023, + 0, + 64, + 3, + 1, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 67, + 0, + -689, + -353, + -319, + -822, + 0, + 240, + 576, + 3, + 1, + 0 + ], + "expected": "956 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + -979, + 88, + 674, + -352, + -1, + 1023, + 64, + 3, + 1, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 69, + 14914603, + -649, + 340, + -868, + -630, + -1, + 240, + 576, + 3, + 1, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 70, + 16777215, + -995, + 244, + 747, + -306, + 1023, + 240, + 64, + 3, + 1, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 71, + 0, + 312, + 912, + -33, + 643, + 1023, + -1024, + 1600, + 3, + 1, + 0 + ], + "expected": "708 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + -232, + 93, + -621, + -222, + 0, + -1, + 96, + 3, + 1, + 4 + ], + "expected": "796 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + 808, + 865, + 145, + 600, + 240, + -1, + 608, + 3, + 1, + 0 + ], + "expected": "1344 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 66, + 16777215, + 788, + -83, + -798, + 173, + 0, + 1023, + 96, + 3, + 1, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 67, + 0, + -192, + -629, + 684, + -1015, + 1023, + 240, + 608, + 3, + 1, + 4 + ], + "expected": "1770 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + -164, + 978, + -548, + -93, + -1, + 1023, + 96, + 3, + 1, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 69, + 14914603, + -90, + 173, + -1020, + 110, + 0, + -1, + 608, + 3, + 1, + 0 + ], + "expected": "1878 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 70, + 16777215, + -396, + 164, + -122, + -258, + -1, + 240, + 1120, + 3, + 1, + 4 + ], + "expected": "862 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 71, + 0, + 702, + -820, + -640, + 816, + 240, + 240, + 608, + 3, + 1, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + -1011, + 76, + -232, + -497, + 1023, + 1023, + 0, + 0, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + 368, + -549, + 4, + -296, + 0, + 0, + 512, + 0, + 2, + 4 + ], + "expected": "746 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 66, + 16777215, + 918, + -569, + -194, + -936, + 0, + -1, + 0, + 0, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 67, + 0, + -1006, + -986, + -160, + -599, + -1, + 240, + 512, + 0, + 2, + 0 + ], + "expected": "1710 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + -1012, + 130, + 717, + 23, + 1023, + 0, + 0, + 0, + 2, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 69, + 14914603, + 712, + -498, + -324, + 410, + 240, + -1, + 1536, + 0, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 70, + 16777215, + 447, + 728, + 166, + 650, + 0, + -1024, + 0, + 0, + 2, + 0 + ], + "expected": "580 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 71, + 0, + 183, + -238, + -945, + 804, + -1, + 240, + 512, + 0, + 2, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + -768, + 381, + -503, + 52, + -1, + 240, + 32, + 0, + 2, + 0 + ], + "expected": "676 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + -928, + -508, + -592, + 417, + -1024, + 0, + 544, + 0, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 66, + 16777215, + -506, + -63, + -223, + 225, + -1024, + 240, + 32, + 0, + 2, + 4 + ], + "expected": "594 d63a91b3c3dc750e91b3f8c610890c19afff17f28ce48a1979a72cb29763ceec" + }, + { + "input": [ + 67, + 0, + -259, + -935, + -66, + -973, + 0, + 0, + 544, + 0, + 2, + 0 + ], + "expected": "404 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + 429, + -777, + -854, + -696, + 1023, + -1, + 1056, + 0, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 69, + 14914603, + 255, + -420, + 928, + 290, + -1024, + 240, + 544, + 0, + 2, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 70, + 16777215, + -347, + -527, + -586, + 343, + 0, + -1024, + 32, + 0, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 71, + 0, + -99, + 514, + 195, + 459, + 0, + -1024, + 544, + 0, + 2, + 0 + ], + "expected": "606 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + 562, + 289, + -963, + 510, + 0, + -1024, + 64, + 0, + 2, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + 727, + -354, + -223, + -646, + 240, + -1, + 576, + 0, + 2, + 0 + ], + "expected": "1918 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 66, + 16777215, + 266, + 575, + 415, + -780, + -1, + 1023, + 64, + 0, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 67, + 0, + 134, + -377, + -572, + 228, + 0, + 1023, + 1600, + 0, + 2, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + 283, + -819, + -58, + 1004, + 0, + -1, + 64, + 0, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 69, + 14914603, + 108, + 207, + 461, + 92, + 1023, + 1023, + 576, + 0, + 2, + 0 + ], + "expected": "724 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 70, + 16777215, + -662, + 424, + -872, + 756, + 240, + 240, + 64, + 0, + 2, + 4 + ], + "expected": "682 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 71, + 0, + -854, + -693, + 963, + -432, + -1, + 0, + 576, + 0, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + 404, + -333, + 784, + 216, + -1024, + -1, + 96, + 0, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + 674, + 546, + 721, + 350, + -1024, + -1, + 608, + 0, + 2, + 4 + ], + "expected": "410 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 66, + 16777215, + 46, + -415, + -494, + -247, + 1023, + 0, + 1120, + 0, + 2, + 0 + ], + "expected": "1098 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 67, + 0, + 961, + 612, + -545, + -150, + 1023, + 1023, + 608, + 0, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + 755, + -580, + -203, + 541, + -1024, + -1024, + 96, + 0, + 2, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 69, + 14914603, + 644, + -406, + 148, + -346, + 1023, + 0, + 608, + 0, + 2, + 0 + ], + "expected": "1010 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 70, + 16777215, + -142, + -316, + -197, + -611, + 240, + -1, + 96, + 0, + 2, + 0 + ], + "expected": "608 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 71, + 0, + 777, + 396, + -321, + -338, + 240, + 240, + 608, + 0, + 2, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + 703, + -938, + -545, + -657, + 0, + -1, + 0, + 1, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + -418, + -583, + -637, + -418, + 1023, + -1024, + 1536, + 1, + 2, + 0 + ], + "expected": "456 433c8fc61cdfefb48baf878bd82fe0d3d5a3b2a448d9388f16929a5d04a4da1a" + }, + { + "input": [ + 66, + 16777215, + 1001, + -889, + -501, + -649, + -1024, + 1023, + 0, + 1, + 2, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 67, + 0, + -539, + 301, + 557, + -742, + 240, + 0, + 512, + 1, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + -482, + -657, + 928, + 421, + -1024, + -1024, + 0, + 1, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 69, + 14914603, + 746, + -386, + -239, + -646, + 240, + -1, + 512, + 1, + 2, + 4 + ], + "expected": "1988 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 70, + 16777215, + -1013, + -632, + -29, + -874, + 240, + -1, + 0, + 1, + 2, + 0 + ], + "expected": "1986 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 71, + 0, + -830, + -484, + -1011, + 859, + 1023, + 0, + 512, + 1, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + -415, + -706, + 705, + 333, + -1, + -1, + 1056, + 1, + 2, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + 329, + -39, + 347, + -310, + -1, + 240, + 544, + 1, + 2, + 0 + ], + "expected": "560 3fc574d7830cbd55212534fa4c36a584efa9e316814f82d063c8f6ba928514bf" + }, + { + "input": [ + 66, + 16777215, + 854, + -1012, + -396, + -538, + 1023, + -1, + 32, + 1, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 67, + 0, + -572, + 303, + -736, + -931, + 0, + -1, + 544, + 1, + 2, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + -180, + 465, + 583, + -326, + 0, + 240, + 32, + 1, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 69, + 14914603, + -940, + -59, + 538, + -417, + -1024, + 1023, + 544, + 1, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 70, + 16777215, + 739, + -157, + 688, + -909, + 1023, + -1024, + 32, + 1, + 2, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 71, + 0, + -215, + 613, + -558, + -313, + -1024, + -1024, + 1568, + 1, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + 236, + 434, + -482, + -443, + 0, + -1024, + 64, + 1, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + 916, + 461, + 33, + 253, + 1023, + 240, + 576, + 1, + 2, + 4 + ], + "expected": "1784 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 66, + 16777215, + 701, + -720, + -323, + 514, + 0, + -1, + 64, + 1, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 67, + 0, + -399, + -709, + 161, + 482, + -1, + 0, + 576, + 1, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + -164, + -463, + 305, + -812, + 0, + -1024, + 64, + 1, + 2, + 4 + ], + "expected": "956 36fe11339d72ff1bd392e07a5199424becdfb8ff581bb180fa9f9328abae7265" + }, + { + "input": [ + 69, + 14914603, + -712, + 248, + 829, + 679, + 0, + 240, + 576, + 1, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 70, + 16777215, + -65, + -836, + 842, + -484, + 240, + -1024, + 1088, + 1, + 2, + 0 + ], + "expected": "1832 51c4cb78552cf5f76172983be1f98a97ad42c91f2e5e16aa2b9e86e0b07c7b2a" + }, + { + "input": [ + 71, + 0, + 419, + 306, + -973, + 736, + 240, + 240, + 576, + 1, + 2, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + 342, + 52, + 446, + -16, + 0, + 1023, + 96, + 1, + 2, + 0 + ], + "expected": "226 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + -170, + -380, + -571, + -307, + 1023, + 240, + 608, + 1, + 2, + 0 + ], + "expected": "820 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 66, + 16777215, + 828, + 1019, + -331, + 813, + -1024, + 240, + 96, + 1, + 2, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 67, + 0, + 982, + 561, + -396, + 498, + -1024, + -1024, + 608, + 1, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + 815, + 218, + 448, + -963, + -1, + 1023, + 96, + 1, + 2, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 69, + 14914603, + -429, + -754, + -997, + 718, + -1, + 240, + 1632, + 1, + 2, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 70, + 16777215, + 200, + -369, + -30, + -220, + 0, + 240, + 96, + 1, + 2, + 0 + ], + "expected": "478 9dd334945ee2063a7f172c6f478aec05c4c9351b4a96740d9abb91e87de1d237" + }, + { + "input": [ + 71, + 0, + 932, + -249, + 888, + -755, + 1023, + 0, + 608, + 1, + 2, + 0 + ], + "expected": "1030 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + 255, + 42, + 250, + -847, + -1, + -1, + 0, + 2, + 0, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + 706, + 645, + 187, + -560, + -1, + -1, + 512, + 2, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 66, + 16777215, + 95, + 465, + -934, + 42, + -1, + 240, + 0, + 2, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 67, + 0, + -354, + -160, + -593, + -561, + -1024, + 0, + 512, + 2, + 0, + 4 + ], + "expected": "820 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + -622, + 81, + 766, + -152, + 1023, + 240, + 1024, + 2, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 69, + 14914603, + -280, + -734, + 943, + -126, + -1024, + -1024, + 512, + 2, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 70, + 16777215, + -786, + 213, + -253, + 858, + -1, + 1023, + 0, + 2, + 0, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 71, + 0, + 782, + -48, + 924, + 864, + -1, + -1024, + 512, + 2, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + -37, + -34, + 276, + 264, + 240, + 1023, + 32, + 2, + 0, + 0 + ], + "expected": "644 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + -324, + 500, + -161, + -569, + 240, + -1, + 544, + 2, + 0, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 66, + 16777215, + -501, + 118, + 686, + 3, + 240, + 0, + 32, + 2, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 67, + 0, + -394, + -824, + -165, + -857, + -1024, + -1024, + 1568, + 2, + 0, + 0 + ], + "expected": "476 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + -988, + 977, + 996, + 471, + 0, + -1, + 32, + 2, + 0, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 69, + 14914603, + 777, + -551, + -450, + -768, + 0, + -1, + 544, + 2, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 70, + 16777215, + 97, + 995, + 662, + 16, + 1023, + -1, + 32, + 2, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 71, + 0, + -787, + 315, + 611, + -763, + -1024, + -1, + 544, + 2, + 0, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + 870, + -342, + -700, + -661, + 0, + 1023, + 64, + 2, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + 172, + 452, + -473, + 127, + 0, + -1, + 576, + 2, + 0, + 0 + ], + "expected": "1308 b1cf3f4cfd594e30f6fb82472809adee2a1a5b106a8d153627a549ea872929b4" + }, + { + "input": [ + 66, + 16777215, + 520, + 468, + -432, + -340, + -1, + 240, + 1088, + 2, + 0, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 67, + 0, + 680, + 390, + 523, + 1023, + -1024, + -1024, + 576, + 2, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + 576, + -708, + 898, + -769, + -1, + -1024, + 64, + 2, + 0, + 0 + ], + "expected": "662 0d43d43a9fb6c7568f2629a575ba73fcb590eeb3116fee91a46e162872933fb9" + }, + { + "input": [ + 69, + 14914603, + 515, + -160, + -355, + -20, + -1, + 0, + 576, + 2, + 0, + 4 + ], + "expected": "1758 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 70, + 16777215, + 145, + 359, + 200, + -920, + -1024, + 240, + 64, + 2, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 71, + 0, + 572, + -853, + -934, + 709, + 1023, + 240, + 576, + 2, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + 307, + -60, + -887, + -354, + -1024, + 240, + 96, + 2, + 0, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + 97, + 300, + 187, + 251, + -1024, + -1024, + 1632, + 2, + 0, + 0 + ], + "expected": "198 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 66, + 16777215, + -436, + -320, + 179, + -45, + -1024, + 240, + 96, + 2, + 0, + 0 + ], + "expected": "1248 71e22ded73e98c37fc209a8c3c3e25d56dc2b4c74eae7d8247aab088a35759bb" + }, + { + "input": [ + 67, + 0, + -258, + 275, + 783, + -979, + 0, + -1, + 608, + 2, + 0, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + 865, + -674, + 164, + -22, + 0, + 0, + 96, + 2, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 69, + 14914603, + -692, + -951, + 919, + -433, + 0, + -1, + 608, + 2, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 70, + 16777215, + -411, + 422, + 860, + 552, + 240, + -1, + 96, + 2, + 0, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 71, + 0, + 785, + -281, + -268, + 809, + 240, + 0, + 608, + 2, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + 82, + -300, + 459, + 493, + 0, + 1023, + 1024, + 3, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + 312, + 781, + 795, + 449, + -1024, + -1024, + 512, + 3, + 0, + 4 + ], + "expected": "984 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 66, + 16777215, + -922, + -206, + -925, + -392, + -1024, + -1024, + 0, + 3, + 0, + 0 + ], + "expected": "390 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 67, + 0, + -888, + -640, + 132, + -648, + 0, + -1024, + 512, + 3, + 0, + 0 + ], + "expected": "2058 bea6858aba8984bc9b1c4eee706b73731b1392d4a62b2d3bbc7d1717d45f7250" + }, + { + "input": [ + 68, + 65280, + -32, + 577, + -930, + 136, + 1023, + 0, + 0, + 3, + 0, + 4 + ], + "expected": "1814 63c8d391dd41ec4fa2366e199597ccc961dce21f78de0784e2b891856778ff66" + }, + { + "input": [ + 69, + 14914603, + -179, + 692, + 692, + 794, + 240, + -1, + 512, + 3, + 0, + 0 + ], + "expected": "1760 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 70, + 16777215, + -962, + -26, + -218, + -845, + 1023, + -1024, + 0, + 3, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 71, + 0, + -952, + -816, + 71, + -722, + 1023, + 1023, + 1536, + 3, + 0, + 4 + ], + "expected": "2064 ac21325d60a27432c31a8dca29f389697595d7a25bb738da49aedf0753a84638" + }, + { + "input": [ + 64, + 65280, + -429, + -121, + -286, + 483, + 240, + -1, + 32, + 3, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + -989, + 300, + 493, + 43, + -1, + 1023, + 544, + 3, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 66, + 16777215, + -175, + 754, + 162, + -980, + 240, + -1024, + 32, + 3, + 0, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 67, + 0, + 415, + 488, + -555, + -695, + -1, + 240, + 544, + 3, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + 113, + -379, + -278, + -398, + -1, + 240, + 32, + 3, + 0, + 0 + ], + "expected": "800 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 69, + 14914603, + -417, + -950, + -995, + -154, + 240, + 1023, + 544, + 3, + 0, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 70, + 16777215, + 976, + -368, + 218, + -345, + 0, + -1, + 1056, + 3, + 0, + 0 + ], + "expected": "1534 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 71, + 0, + -127, + 1020, + 540, + 825, + 0, + -1024, + 544, + 3, + 0, + 0 + ], + "expected": "1352 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + -687, + 621, + 282, + -342, + 0, + -1024, + 64, + 3, + 0, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + 137, + -906, + -66, + -454, + -1024, + 1023, + 576, + 3, + 0, + 0 + ], + "expected": "922 f475b5f95cd266b0ce791dc68cce5130624a767594aa7c982d5aa2f98611d4c6" + }, + { + "input": [ + 66, + 16777215, + -453, + 380, + 238, + 354, + 1023, + 0, + 64, + 3, + 0, + 0 + ], + "expected": "1400 4a07c22cb78f9e895c2013b2207c2f0596b3eec093fe5a825b229e01b4306fc9" + }, + { + "input": [ + 67, + 0, + -772, + 948, + -335, + 322, + 0, + -1, + 576, + 3, + 0, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + -699, + 425, + -386, + 423, + -1, + 240, + 64, + 3, + 0, + 0 + ], + "expected": "644 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 69, + 14914603, + -365, + -1021, + -860, + -577, + 1023, + 240, + 1600, + 3, + 0, + 0 + ], + "expected": "1008 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 70, + 16777215, + 528, + 139, + 360, + -457, + -1024, + 240, + 64, + 3, + 0, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 71, + 0, + -695, + -584, + -865, + 988, + 0, + 1023, + 576, + 3, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 64, + 65280, + 852, + -676, + -454, + -479, + 1023, + 240, + 96, + 3, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 65, + 14914603, + 959, + 671, + -582, + -530, + -1024, + 0, + 608, + 3, + 0, + 4 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 66, + 16777215, + -960, + -872, + -1002, + 637, + -1, + 0, + 96, + 3, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 67, + 0, + -634, + -150, + 622, + -571, + -1024, + -1, + 608, + 3, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 68, + 65280, + -801, + 695, + -807, + 903, + -1024, + -1024, + 1120, + 3, + 0, + 4 + ], + "expected": "434 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 69, + 14914603, + -188, + -496, + -396, + 925, + 240, + 240, + 608, + 3, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 70, + 16777215, + -933, + -297, + 753, + 99, + 0, + -1024, + 96, + 3, + 0, + 0 + ], + "expected": "18 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + }, + { + "input": [ + 71, + 0, + 1016, + -342, + 221, + 49, + 1023, + 1023, + 608, + 3, + 0, + 4 + ], + "expected": "1608 accce316ea030a7432502667f2233874668666a6ea83745a104930f83765f0ca" + } + ] +} diff --git a/runtime/tests/test_source_gpu_command_projection.c b/runtime/tests/test_source_gpu_command_projection.c index b058d4e5..48059ab4 100644 --- a/runtime/tests/test_source_gpu_command_projection.c +++ b/runtime/tests/test_source_gpu_command_projection.c @@ -60,7 +60,7 @@ int main(int argc,char **argv) { assert(source_gpu_command_update(&s,595)); assert(s.second_triangles==1); assert(source_gpu_command_update(&s,638)); assert(s.second_triangles==2 && s.budget==-45); assert(!source_gpu_command_update(&s,637)); assert(s.error==SOURCE_GPU_COMMAND_REVERSE_TIME); - setup(&s); assert(!source_gpu_command_write(&s,0x40000000)); + setup(&s); assert(!source_gpu_command_write(&s,0x48000000)); assert(s.error==SOURCE_GPU_COMMAND_UNSUPPORTED); setup(&s); assert(source_gpu_command_update(&s,146)); quad(&s,32); for(unsigned i=1;i<16;++i) assert(source_gpu_command_write(&s,0)); diff --git a/runtime/tests/test_source_gpu_flat_blend.c b/runtime/tests/test_source_gpu_flat_blend.c index a16ab062..6a85338a 100644 --- a/runtime/tests/test_source_gpu_flat_blend.c +++ b/runtime/tests/test_source_gpu_flat_blend.c @@ -74,6 +74,6 @@ int main(int argc,char **argv) { const unsigned opcodes[]={0x20,0x21,0x22,0x23,0x28,0x29,0x2a,0x2b}; for(unsigned op=0;op<8;op++)for(unsigned blend=0;blend<4;blend++)for(unsigned mask=0;mask<4;mask++)run(opcodes[op],blend,mask); SourceGPUCommandProjection s;source_gpu_command_cold(&s); - check(!source_gpu_command_write(&s,0x40000000) && s.error==SOURCE_GPU_COMMAND_UNSUPPORTED,"unqualified line commands still fail closed"); + check(!source_gpu_command_write(&s,0x48000000) && s.error==SOURCE_GPU_COMMAND_UNSUPPORTED,"unqualified polyline commands still fail closed"); printf("source_gpu_flat_blend: %u checks passed\n",checks); } diff --git a/runtime/tests/test_source_gpu_line.c b/runtime/tests/test_source_gpu_line.c new file mode 100644 index 00000000..905df378 --- /dev/null +++ b/runtime/tests/test_source_gpu_line.c @@ -0,0 +1,43 @@ +/* Authored input cases are compared against the retained source oracle hashes. */ +#include "source_gpu_command_projection.h" +#include "gpu_sw_renderer.h" +#include "psx_sha256.h" +#include +#include +#include +static uint16_t vram[1024*512]; +int g_ws_bd_stretch_on,g_ws_bd_stretch_pct; +int psx_ws_prim_in_backdrop(void){abort();} +int main(void) { + unsigned op,color,mode,mask,field; + int x0,y0,x1,y1,ox,oy,clip; + while(scanf("%u %u %d %d %d %d %d %d %u %u %u %d",&op,&color,&x0,&y0,&x1,&y1,&ox,&oy,&mode,&mask,&field,&clip)==12) { + uint32_t words[]={op<<24|color,((uint32_t)y0&65535u)<<16|((uint32_t)x0&65535u),((uint32_t)y1&65535u)<<16|((uint32_t)x1&65535u)}; + SourceGPUCommandProjection s;source_gpu_command_cold(&s); + s.clip_x0=s.clip_y0=clip;s.clip_x1=1023-clip;s.clip_y1=511-clip; + s.budget=256;s.offset_x=ox;s.offset_y=oy;s.draw_mode=mode; + s.display_mode=field?0x24:0;s.field_valid=1;s.skip_field=field==2;s.mask_bits=mask; + assert(source_gpu_command_length(words[0])==3); + assert(source_gpu_command_feedback_length(words[0])==1); + for(unsigned i=0;i<2;i++){assert(source_gpu_command_write(&s,words[i]));assert(s.dispatch.kind==0);} + assert(!source_gpu_command_ready(&s)); + assert(source_gpu_command_write(&s,words[2])); + assert(s.dispatch.kind==SOURCE_GPU_DISPATCH_COMMAND && s.dispatch.count==3 && !s.count); + for(unsigned i=0;i<1024*512;i++)vram[i]=(uint16_t)(i*37u+0x1234u); + sw_renderer_init(vram);sw_set_mask_bits(mask&1,!!(mask&2));sw_set_semi_transparency(!!(op&2),(mode>>5)&3); + SourceGPUBlock b={0};b.words=words;b.draw_mode=mode; + b.x=source_gpu_command_coord(words[1],0)+ox;b.y=source_gpu_command_coord(words[1],16)+oy; + b.clip_left=b.clip_top=clip;b.clip_right=1023-clip;b.clip_bottom=511-clip; + b.interlace=field && !(mode&1024);b.skip_field=field==2; + int extra=-1;assert(sw_draw_source_block(&b,&extra) && extra==0); + uint8_t hash[32];psx_sha256_compute((uint8_t*)vram,sizeof(vram),hash); + printf("%d ",256-s.budget);for(unsigned i=0;i<32;i++)printf("%02x",hash[i]);puts(""); + } + SourceGPUCommandProjection s;source_gpu_command_cold(&s); + s.budget=-1;s.clip_x1=1023;s.clip_y1=511; + assert(source_gpu_command_write(&s,0x4000ff00));assert(source_gpu_command_write(&s,0x00a20054)); + assert(source_gpu_command_write(&s,0x00a20054));assert(s.count==3 && !s.dispatch.kind); + assert(source_gpu_command_update(&s,1));assert(!s.count && s.budget==-17); + source_gpu_command_cold(&s);assert(!source_gpu_command_write(&s,0x48000000)); + return 0; +} diff --git a/runtime/tests/test_source_gpu_line_contracts.py b/runtime/tests/test_source_gpu_line_contracts.py new file mode 100644 index 00000000..eb7a0592 --- /dev/null +++ b/runtime/tests/test_source_gpu_line_contracts.py @@ -0,0 +1,12 @@ +"""Check complete VRAM hashes and timing against authored source-line fixtures.""" +import json, os, subprocess, sys +from pathlib import Path +fixture=json.loads(Path(__file__).with_name('source_gpu_line_fixtures.json').read_text()) +env={k:v for k,v in os.environ.items() if not k.startswith('PSX_')} +r=subprocess.run([sys.argv[1]],input=''.join(' '.join(map(str,c['input']))+'\n' for c in fixture['cases']),capture_output=True,text=True,env=env,timeout=120) +assert r.returncode==0,(r.returncode,r.stderr) +rows=r.stdout.splitlines() +assert len(rows)==len(fixture['cases']) +for row,case in zip(rows,fixture['cases']): + assert row==case['expected'],(case['input'],row,case['expected']) +print(f"{len(rows)} source line timing and complete VRAM hashes PASS") diff --git a/tools/tasreplays/source_line_oracle.py b/tools/tasreplays/source_line_oracle.py new file mode 100644 index 00000000..6bab065f --- /dev/null +++ b/tools/tasreplays/source_line_oracle.py @@ -0,0 +1,63 @@ +"""Generate authored line fixtures using unedited Nymashock source functions. + +Builds extracted reference functions only in the supplied private output folder. +This is a component oracle, not an unmodified-core or full-replay qualification. +""" +import argparse, hashlib, json, random, subprocess +from pathlib import Path + +p=argparse.ArgumentParser(description=__doc__) +p.add_argument('--source',type=Path,required=True) +p.add_argument('--output',type=Path,required=True) +a=p.parse_args();a.output.mkdir(parents=True,exist_ok=False) +root=Path(__file__).resolve().parents[2] +line=(a.source/'gpu_line.cpp').read_text();common=(a.source/'gpu_common.inc').read_text() +plot=common[common.index('template'):common.index('static INLINE uint16 ModTexel')] +skip=common[common.index('static INLINE bool LineSkipTest'):common.index('static INLINE bool LineSkipTest')+common[common.index('static INLINE bool LineSkipTest'):].index('\n}')+2] +body=line[line.index('struct line_fxp_coord'):line.index('MDFN_HIDE extern const CTEntry')] +prefix='''#include +#include +#include +#include "psx_sha256.h" +using uint8=uint8_t;using uint16=uint16_t;using uint32=uint32_t;using uint64=uint64_t; +using int32=int32_t;using int64=int64_t; +#define INLINE inline +static uint16 GPURAM[512][1024]; +static int ClipX0,ClipY0,ClipX1,ClipY1,OffsX,OffsY,DrawTimeAvail,dtd,dfe,MaskSetOR,MaskEvalAND; +static unsigned DisplayMode,DisplayFB_YStart,field_ram_readout; +static uint8 DitherLUT[4][4][256]; +struct line_point {int32 x,y;uint8 r,g,b;}; +struct PS_GPU {enum {INCMD_PLINE=1};}; +static int InCmd,InCmd_CC;static line_point InPLine_PrevPoint; +static int sign_x_to_s32(unsigned bits,unsigned value){unsigned mask=1u<<(bits-1);return int((value&((mask<<1)-1))^mask)-int(mask);} +''' +dispatch='\n'.join(f'case {b}: if(mask&2)Command_DrawLine(words);else Command_DrawLine(words);break;' for b in range(-1,4)) +main='''int main(){unsigned op,color,mode,mask,field;int x0,y0,x1,y1,ox,oy,clip; +const int matrix[4][4]={{-4,0,-3,1},{2,-2,3,-1},{-3,1,-4,0},{3,-1,2,-2}}; +for(int y=0;y<4;y++)for(int x=0;x<4;x++)for(int c=0;c<256;c++){int v=c+matrix[y][x];if(v<0)v=0;if(v>255)v=255;DitherLUT[y][x][c]=v>>3;} +while(scanf("%u %u %d %d %d %d %d %d %u %u %u %d",&op,&color,&x0,&y0,&x1,&y1,&ox,&oy,&mode,&mask,&field,&clip)==12){ +for(unsigned i=0;i<512*1024;i++)GPURAM[i/1024][i%1024]=(uint16)(i*37u+0x1234u); +ClipX0=ClipY0=clip;ClipX1=1023-clip;ClipY1=511-clip;OffsX=ox;OffsY=oy; +MaskSetOR=(mask&1)?0x8000:0;MaskEvalAND=(mask&2)?0x8000:0;dtd=!!(mode&512);dfe=!!(mode&1024); +DisplayMode=field?0x24:0;DisplayFB_YStart=0;field_ram_readout=field==2; +uint32 words[]={op<<24|color,((uint32)y0&65535u)<<16|((uint32)x0&65535u),((uint32)y1&65535u)<<16|((uint32)x1&65535u)}; +DrawTimeAvail=254;switch((op&2)?int((mode>>5)&3):-1){DISPATCH} +uint8 hash[32];psx_sha256_compute((uint8*)GPURAM,sizeof(GPURAM),hash); +printf("%d ",256-DrawTimeAvail);for(unsigned i=0;i<32;i++)printf("%02x",hash[i]);puts("");}} +'''.replace('DISPATCH',dispatch) +cpp=a.output/'source-line.cpp';cpp.write_text(prefix+plot+skip+body+main) +exe=a.output/'source-line.exe' +subprocess.run(['g++','-O2','-I'+str(root/'runtime/include'),str(cpp),str(root/'runtime/src/psx_sha256.c'),'-o',str(exe)],check=True) +rng=random.Random(20371) +geometries=[(84,162,84,162),(0,0,0,0),(4,4,12,4),(4,4,4,12),(4,4,12,8),(12,8,4,4),(4,12,12,4),(-1,-1,8,8),(0,0,1023,511),(0,0,1024,0),(0,0,0,512),(1023,511,1023,511),(-1024,-1024,-1024,-1024)] +cases=[] +for i in range(256): + xy=geometries[i%len(geometries)] if i<104 else tuple(rng.randrange(-1024,1024) for _ in range(4)) + cases.append([0x40+i%8,[0x00ff00,0xe3942b,0xffffff,0][i%4],*xy,0 if i<104 else rng.choice([-1024,-1,0,240,1023]),240 if i==0 else 0 if i<104 else rng.choice([-1024,-1,0,240,1023]),((i//8)%4)*32+(512 if i&1 else 0)+(1024 if i%7==0 else 0),(i//32)%4,(i//64)%3,0 if i%3 else 4]) +cases[0]=[0x40,0x00ff00,84,162,84,162,0,240,512,0,0,0] +r=subprocess.run([str(exe)],input=''.join(' '.join(map(str,c))+'\n' for c in cases),capture_output=True,text=True,check=True,timeout=120) +rows=r.stdout.splitlines();assert len(rows)==len(cases) +sha=lambda p:hashlib.sha256(p.read_bytes()).hexdigest() +receipt={'scope':__doc__,'source_files':[{'path':str(a.source/n),'sha256':sha(a.source/n)} for n in ['gpu_line.cpp','gpu_common.inc']], 'driver_sha256':sha(Path(__file__)),'extracted_harness_sha256':sha(cpp),'cases':[{'input':c,'expected':row} for c,row in zip(cases,rows)]} +(a.output/'fixtures.json').write_text(json.dumps(receipt,indent=2)+'\n') +print(a.output/'fixtures.json')