{"id":11758,"date":"2026-11-06T18:39:46","date_gmt":"2026-11-06T17:39:46","guid":{"rendered":"https:\/\/retrofixer.it\/?page_id=11758"},"modified":"2026-11-06T18:39:46","modified_gmt":"2026-11-06T17:39:46","slug":"identificatore-rom","status":"publish","type":"page","link":"https:\/\/retrofixer.it\/en\/identificatore-rom\/","title":{"rendered":"ROM identifier"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"11758\" class=\"elementor elementor-11758\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-169e1ef e-con-full e-flex e-con e-parent\" data-id=\"169e1ef\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-9c4d7d9 elementor-widget elementor-widget-html\" data-id=\"9c4d7d9\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\n<link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin>\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Press+Start+2P&family=VT323&family=Inter:wght@400;500;600;700&display=swap\" rel=\"stylesheet\">\n<style>\n.rfri{--bg:#0f0c24;--bg2:#171338;--panel:#1d1846;--line:#342c74;--text:#eceaff;--muted:#aaa5d8;--yel:#ffd23f;--cya:#3fd8ff;--mag:#e0398a;--grn:#5ad15f;--red:#f94144;--ora:#f8961e;--pho:#7dff8a;\n  font-family:'Inter',system-ui,-apple-system,Segoe UI,Roboto,sans-serif;color:var(--text);background:var(--bg);line-height:1.5;padding:36px 0 40px}\n.rfri *,.rfri *::before,.rfri *::after{box-sizing:border-box}\n.rfri h2,.rfri h3,.rfri h4,.rfri p,.rfri ul{margin:0;padding:0}\n.rfri h2,.rfri h3,.rfri h4{font-family:'Inter',system-ui,sans-serif!important;letter-spacing:0;text-transform:none;font-weight:700;color:#fff}\n.rfri a{color:var(--cya)}\n.rfri button{font:inherit;color:inherit;cursor:pointer}\n.rfri [hidden]{display:none!important}\nbody:has(#rfri) .post-views{background:#0f0c24;color:#aaa5d8;margin:0;padding:0 16px 8px;font-size:13px}\n.rfri .wrap{max-width:1100px;margin:0 auto;padding:0 16px}\n.rfri .stripe{height:6px;background:linear-gradient(90deg,var(--red) 0 16.6%,var(--ora) 0 33.3%,var(--yel) 0 50%,var(--grn) 0 66.6%,var(--cya) 0 83.3%,#7c70da 0);margin-bottom:28px}\n.rfri .kicker{font-family:'Press Start 2P',monospace;font-size:10px;color:var(--yel);display:block;margin-bottom:10px}\n.rfri .h2{font-family:'Press Start 2P',monospace!important;font-size:clamp(17px,2.8vw,26px);line-height:1.45;margin-bottom:12px}\n.rfri .sub{color:var(--muted);max-width:860px;font-size:16px}\n.rfri .drop{margin:22px 0 8px;border:3px dashed var(--line);border-radius:14px;background:var(--bg2);padding:28px 20px;text-align:center;transition:border-color .15s,background .15s}\n.rfri .drop.over{border-color:var(--cya);background:var(--panel)}\n.rfri .drop b{display:block;font-size:18px;color:#fff;margin-bottom:6px}\n.rfri .drop span{font-size:14px;color:var(--muted)}\n.rfri .drop .btn{margin-top:14px}\n.rfri .btn{display:inline-block;background:#7c70da;border:0;border-radius:8px;padding:10px 18px;color:#fff;font-weight:600;font-size:15px}\n.rfri .btn:hover{background:#9488ef}\n.rfri .note{font-size:13px;color:var(--muted);margin-bottom:18px}\n.rfri .file{background:var(--panel);border:2px solid var(--line);border-radius:14px;padding:18px 20px;margin-top:16px}\n.rfri .file .top{display:flex;flex-wrap:wrap;gap:8px 16px;align-items:baseline;justify-content:space-between;margin-bottom:12px}\n.rfri .file h3{font-size:18px;word-break:break-all}\n.rfri .badge{font-family:'Press Start 2P',monospace;font-size:9px;padding:6px 8px;border-radius:6px;color:#0f0c24;background:var(--muted)}\n.rfri .badge.ok{background:var(--grn)}.rfri .badge.warn{background:var(--yel)}.rfri .badge.bad{background:var(--red);color:#fff}.rfri .badge.unk{background:#7c70da;color:#fff}\n.rfri .facts{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:8px 16px;margin-bottom:14px}\n.rfri .facts div{background:var(--bg2);border:1px solid var(--line);border-radius:8px;padding:8px 10px}\n.rfri .facts small{display:block;font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}\n.rfri .facts code{font-family:'VT323',monospace;font-size:19px;color:var(--pho);word-break:break-all}\n.rfri .msgs{display:flex;flex-direction:column;gap:6px;margin-bottom:12px}\n.rfri .msg{border-left:4px solid var(--cya);background:var(--bg2);border-radius:6px;padding:8px 12px;font-size:14px}\n.rfri .msg.ok{border-color:var(--grn)}.rfri .msg.warn{border-color:var(--yel)}.rfri .msg.bad{border-color:var(--red)}\n.rfri .match{background:var(--bg2);border:1px solid var(--line);border-radius:10px;padding:12px 14px;margin-top:10px}\n.rfri .match h4{font-size:15px;margin-bottom:4px}\n.rfri .match .how{font-size:12.5px;color:var(--muted);margin-bottom:6px}\n.rfri .match ul{padding-left:18px}\n.rfri .match li{font-size:14px;color:var(--text);margin:3px 0}\n.rfri .match li small{color:var(--muted)}\n.rfri .kind{display:inline-block;font-size:10.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;border-radius:4px;padding:1px 6px;margin-left:6px;background:var(--line);color:#fff}\n.rfri .strs{font-family:'VT323',monospace;font-size:17px;color:var(--muted);background:#07060f;border-radius:8px;padding:8px 12px;margin-top:10px;max-height:160px;overflow:auto;white-space:pre-wrap;word-break:break-all}\n.rfri .help{margin-top:30px;display:grid;grid-template-columns:1fr 1fr;gap:16px}\n.rfri .help .box{background:var(--bg2);border:1px solid var(--line);border-radius:12px;padding:14px 16px}\n.rfri .help h4{font-size:15px;margin-bottom:8px}\n.rfri .help li{font-size:14px;color:var(--muted);margin:4px 0 4px 18px}\n.rfri table.ep{width:100%;border-collapse:collapse;font-size:13.5px}\n.rfri table.ep td,.rfri table.ep th{border:1px solid var(--line);padding:4px 8px;text-align:left}\n.rfri table.ep th{color:#fff;background:var(--panel)}\n.rfri .foot{margin-top:24px;font-size:13px;color:var(--muted)}\n.rfri .spin{display:inline-block;width:14px;height:14px;border:2px solid var(--cya);border-right-color:transparent;border-radius:50%;animation:rfrisp .8s linear infinite;vertical-align:-2px;margin-right:6px}\n@keyframes rfrisp{to{transform:rotate(360deg)}}\n@media (max-width:760px){.rfri .help{grid-template-columns:1fr}}\n<\/style>\n\n<div class=\"rfri\" id=\"rfri\" data-no-translation data-db=\"\/wp-content\/uploads\/2026\/11\/\">\n  <div class=\"stripe\"><\/div>\n  <div class=\"wrap\">\n    <span class=\"kicker\" data-t=\"kick\"><\/span>\n    <h2 class=\"h2\" data-t=\"title\"><\/h2>\n    <p class=\"sub\" data-t=\"intro\"><\/p>\n    <label class=\"drop\" id=\"rfriDrop\">\n      <b data-t=\"drop\"><\/b>\n      <span data-t=\"drop2\"><\/span><br>\n      <span class=\"btn\" data-t=\"pick\"><\/span>\n      <input type=\"file\" id=\"rfriIn\" multiple hidden>\n    <\/label>\n    <p class=\"note\" data-t=\"privacy\"><\/p>\n    <div class=\"msg\" style=\"margin-bottom:18px\"><b style=\"color:#fff\" data-t=\"dbver\"><\/b> <span data-t=\"dbver2\"><\/span><\/div>\n    <div id=\"rfriOut\"><\/div>\n    <div class=\"help\">\n      <div class=\"box\"><h4 data-t=\"h1\"><\/h4><ul id=\"rfriTips\"><\/ul><\/div>\n      <div class=\"box\"><h4 data-t=\"h2\"><\/h4><table class=\"ep\" id=\"rfriEp\"><\/table><\/div>\n    <\/div>\n    <p class=\"foot\" data-t=\"foot\"><\/p>\n  <\/div>\n<\/div>\n\n<script>\n(function () {\n  var root = document.getElementById('rfri');\n  if (!root || root.getAttribute('data-ready')) return;\n  root.setAttribute('data-ready', '1');\n  var EN = \/^en\/i.test(document.documentElement.lang || '');\n  var L = EN ? 1 : 0;\n  function t(p) { return p[L]; }\n  function $(id) { return document.getElementById(id); }\n  function esc(s) { return String(s == null ? '' : s).replace(\/[&<>\"']\/g, function (c) { return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;', \"'\": '&#39;' }[c]; }); }\n  var DB = root.getAttribute('data-db');\n  var UI = {\n    kick: ['IDENTIFICATORE DI ROM', 'ROM IDENTIFIER'],\n    title: ['Che ROM \u00e8? Carica il dump e scoprilo', 'Which ROM is it? Load the dump and find out'],\n    intro: ['Carica il file letto dal programmatore di EPROM: ti diciamo quanto \u00e8 grande, se \u00e8 vuota o sospetta e, se la troviamo nell\\'archivio, di che computer, console, scheda arcade o periferica \u00e8 (KERNAL, BASIC, caratteri, BIOS, Kickstart, ROM dei drive e molto altro).',\n            'Load the file read by your EPROM programmer: we tell you how big it is, whether it is blank or suspicious and, if we find it in the archive, which computer, console, arcade board or peripheral it comes from (KERNAL, BASIC, character ROM, BIOS, Kickstart, drive ROMs and much more).'],\n    drop: ['Trascina qui uno o pi\u00f9 file ROM', 'Drop one or more ROM files here'],\n    drop2: ['.bin, .rom, .hex (Intel HEX), .s19\/.srec (Motorola), .prg, .crt, .nes, .smc, .z64\/.v64\/.n64 e altri', '.bin, .rom, .hex (Intel HEX), .s19\/.srec (Motorola), .prg, .crt, .nes, .smc, .z64\/.v64\/.n64 and more'],\n    pick: ['Scegli i file', 'Choose files'],\n    privacy: ['Il file non viene inviato da nessuna parte: l\\'analisi avviene nel tuo browser. Dal sito scarichiamo solo la parte di archivio che serve per il checksum calcolato.',\n              'Your file is not sent anywhere: the analysis runs in your browser. From the site we only download the part of the archive needed for the computed checksum.'],\n    dbver: ['Archivio: MAME 0.289 (30 luglio 2026), 158.349 ROM.', 'Archive: MAME 0.289 (30 July 2026), 158,349 ROMs.'],\n    dbver2: ['Se una ROM non viene trovata, pu\u00f2 darsi che sia stata catalogata in una versione pi\u00f9 recente di MAME: aggiorneremo l\\'archivio periodicamente.', 'If a ROM is not found, it may have been catalogued in a newer MAME release: we will update the archive from time to time.'],\n    h1: ['Consigli per un buon dump', 'Tips for a good dump'],\n    h2: ['Dimensioni delle EPROM pi\u00f9 comuni', 'Common EPROM sizes'],\n    foot: ['Archivio: checksum e nomi delle ROM elencate da MAME 0.289 (mamedev.org), oltre 158.000 ROM di arcade, computer, console, BIOS e periferiche. Le ROM non sono incluse. Un dump non trovato non \u00e8 per forza guasto: pu\u00f2 essere una versione rara, modificata o non ancora catalogata.',\n           'Archive: checksums and names of the ROMs listed by MAME 0.289 (mamedev.org), over 158,000 ROMs from arcade boards, computers, consoles, BIOSes and peripherals. No ROMs are included. A dump that is not found is not necessarily bad: it may be a rare, modified or not yet catalogued version.'],\n    size: ['Dimensione', 'Size'], crc: ['CRC32', 'CRC32'], sha: ['SHA-1', 'SHA-1'], eprom: ['Chip compatibile', 'Matching chip'], fmt: ['Formato', 'Format'],\n    reading: ['Lettura e ricerca nell\\'archivio\u2026', 'Reading and searching the archive\u2026'],\n    found: ['TROVATA', 'FOUND'], notfound: ['SCONOSCIUTA', 'UNKNOWN'], blank: ['VUOTA', 'BLANK'], suspect: ['SOSPETTA', 'SUSPECT'],\n    whole: ['File intero', 'Whole file'],\n    usedin: ['usata in', 'used in'], machines: ['macchine', 'machines'], andmore: ['e altre', 'and more'],\n    sha1ok: ['confermata anche dallo SHA-1', 'also confirmed by SHA-1'], sha1no: ['CRC uguale ma SHA-1 diverso: probabile coincidenza o variante', 'Same CRC but different SHA-1: likely a coincidence or a variant'],\n    nomatch: ['Non trovata nell\\'archivio (MAME 0.289, luglio 2026): pu\u00f2 essere una versione rara, modificata, guasta o catalogata dopo.', 'Not found in the archive (MAME 0.289, July 2026): it may be a rare, modified or damaged version, or one catalogued later.'],\n    strings: ['Testi leggibili nel file (possono aiutare a capire cos\\'\u00e8)', 'Readable text in the file (it may help to tell what it is)'],\n    dberr: ['Non riesco a scaricare l\\'archivio: riprova pi\u00f9 tardi.', 'Cannot download the archive: please try again later.'],\n    pair: ['Coppia di file', 'File pair']\n  };\n  var KINDS = { a: ['arcade', 'arcade'], s: ['computer\/console', 'computer\/console'], b: ['BIOS', 'BIOS'], d: ['periferica\/scheda', 'peripheral\/board'], m: ['slot\/flipper', 'slot\/pinball'] };\n  var TIPS = [\n    ['Leggi la ROM almeno due volte e confronta i file: se cambiano, il chip o lo zoccolo non \u00e8 affidabile.', 'Read the ROM at least twice and compare the files: if they differ, the chip or socket is unreliable.'],\n    ['Scegli nel programmatore il tipo esatto di chip: un 2764 letto come 27128 d\u00e0 il contenuto ripetuto due volte (lo riconosciamo lo stesso).', 'Select the exact chip type on the programmer: a 2764 read as a 27128 gives the content twice (we still recognise it).'],\n    ['Le ROM a maschera Commodore (es. 901227) non hanno la piedinatura delle EPROM: serve un adattatore o la lettura in modalit\u00e0 giusta.', 'Commodore mask ROMs (e.g. 901227) do not share the EPROM pinout: you need an adapter or the right read mode.'],\n    ['Tutti FF di solito vuol dire chip vuoto o non letto (pin non a contatto); tutti 00 chip non alimentato o corto.', 'All FF usually means a blank or unread chip (pins not touching); all 00 an unpowered chip or a short.'],\n    ['Per le ROM a 16 bit divise in due chip (pari e dispari, alta e bassa) carica tutti e due i file: proviamo anche a unirli.', 'For 16-bit ROMs split across two chips (even and odd, high and low) load both files: we also try joining them.']\n  ];\n  var EPROMS = [['2716', 2048], ['2732', 4096], ['2764', 8192], ['27128', 16384], ['27256', 32768], ['27512', 65536], ['27C010 \/ 27C1001', 131072], ['27C020 \/ 27C2001', 262144], ['27C040 \/ 27C4001', 524288], ['27C400 (16 bit)', 524288], ['27C080 \/ 27C800', 1048576], ['27C160', 2097152]];\n  [].forEach.call(root.querySelectorAll('[data-t]'), function (e) { e.textContent = t(UI[e.getAttribute('data-t')]); });\n  $('rfriTips').innerHTML = TIPS.map(function (x) { return '<li>' + esc(t(x)) + '<\/li>'; }).join('');\n  $('rfriEp').innerHTML = '<tr><th>Chip<\/th><th>KB<\/th><th>Byte<\/th><\/tr>' + EPROMS.map(function (e) { return '<tr><td>' + e[0] + '<\/td><td>' + (e[1] \/ 1024) + '<\/td><td>' + e[1] + '<\/td><\/tr>'; }).join('');\n\n  \/* ---------- checksum ---------- *\/\n  var CRCT = (function () { var tb = new Uint32Array(256); for (var n = 0; n < 256; n++) { var c = n; for (var k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1; tb[n] = c >>> 0; } return tb; })();\n  function crc32(b) { var c = 0xffffffff; for (var i = 0; i < b.length; i++) c = CRCT[(c ^ b[i]) & 255] ^ (c >>> 8); return ((c ^ 0xffffffff) >>> 0).toString(16).padStart(8, '0'); }\n  function sha1(b) {\n    if (!(window.crypto && crypto.subtle)) return Promise.resolve('');\n    return crypto.subtle.digest('SHA-1', b).then(function (h) { return Array.prototype.map.call(new Uint8Array(h), function (x) { return x.toString(16).padStart(2, '0'); }).join(''); });\n  }\n  function hex(n, w) { return n.toString(16).toUpperCase().padStart(w || 0, '0'); }\n  function sizeTxt(n) { return n >= 1024 ? (n \/ 1024 % 1 ? (n \/ 1024).toFixed(2) : n \/ 1024) + ' KB (' + n + ' byte, $' + hex(n) + ')' : n + ' byte'; }\n  function epromFor(n) { var r = EPROMS.filter(function (e) { return e[1] === n; }).map(function (e) { return e[0]; }); return r.length ? r.join(' \u00b7 ') : (EN ? 'not a standard size' : 'dimensione non standard'); }\n\n  \/* ---------- archivio (64 file per CRC) ---------- *\/\n  var cache = {};\n  function shard(crc) { var i = parseInt(crc.slice(0, 2), 16) >> 2; return (i < 10 ? '0' : '') + i; }\n  function loadShard(s) {\n    if (!cache[s]) cache[s] = fetch(DB + 'rfrom-' + s + '.txt').then(function (r) { if (!r.ok) throw new Error(r.status); return r.text(); }).then(function (txt) {\n      var m = {}; txt.split('\\n').slice(1).forEach(function (l) { if (l) { var k = l.slice(0, 8); (m[k] = m[k] || []).push(l); } }); return m;\n    });\n    return cache[s];\n  }\n  function lookup(crc, size) {\n    return loadShard(shard(crc)).then(function (m) {\n      return (m[crc] || []).map(function (l) {\n        var p = l.split('\\t');\n        return { size: +p[1], sha: p[2], names: p[3], count: +p[4], machines: p[5] ? p[5].split(';').map(function (x) { var q = x.split('|'); return { n: q[0], d: q[1], y: q[2], m: q[3], k: q[4] }; }) : [] };\n      }).filter(function (e) { return e.size === size; });\n    });\n  }\n\n  \/* ---------- formati ---------- *\/\n  function isText(b) { var n = Math.min(b.length, 4096), bad = 0; for (var i = 0; i < n; i++) { var c = b[i]; if (c < 9 || (c > 13 && c < 32) || c > 126) bad++; } return bad === 0; }\n  function parseHex(txt) {\n    var lines = txt.split(\/\\r?\\n\/).map(function (l) { return l.trim(); }).filter(Boolean), mem = {}, lo = Infinity, hi = -1, base = 0, ok = 0;\n    if (lines[0].charAt(0) === ':') {\n      lines.forEach(function (l) {\n        if (l.charAt(0) !== ':') return;\n        var n = parseInt(l.substr(1, 2), 16), a = parseInt(l.substr(3, 4), 16), ty = parseInt(l.substr(7, 2), 16);\n        if (ty === 0) { for (var i = 0; i < n; i++) { var ad = base + a + i; mem[ad] = parseInt(l.substr(9 + i * 2, 2), 16); lo = Math.min(lo, ad); hi = Math.max(hi, ad); } ok++; }\n        else if (ty === 2) base = parseInt(l.substr(9, 4), 16) * 16;\n        else if (ty === 4) base = parseInt(l.substr(9, 4), 16) * 65536;\n      });\n      return ok ? { fmt: 'Intel HEX', mem: mem, lo: lo, hi: hi } : null;\n    }\n    if (\/^S[0-9]\/.test(lines[0])) {\n      lines.forEach(function (l) {\n        var ty = l.charAt(1), n = parseInt(l.substr(2, 2), 16), al = ty === '1' ? 4 : ty === '2' ? 6 : ty === '3' ? 8 : 0;\n        if (!al) return;\n        var a = parseInt(l.substr(4, al), 16), cnt = n - al \/ 2 - 1;\n        for (var i = 0; i < cnt; i++) { var ad = a + i; mem[ad] = parseInt(l.substr(4 + al + i * 2, 2), 16); lo = Math.min(lo, ad); hi = Math.max(hi, ad); }\n        ok++;\n      });\n      return ok ? { fmt: 'Motorola S-record', mem: mem, lo: lo, hi: hi } : null;\n    }\n    return null;\n  }\n  function fromHex(h) {\n    var n = h.hi - h.lo + 1, b = new Uint8Array(n).fill(0xff);\n    for (var a in h.mem) b[a - h.lo] = h.mem[a];\n    return b;\n  }\n  \/\/ varianti da cercare: file intero, intestazioni tolte, parti, ordine dei byte\n  function variants(name, b) {\n    var out = [], low = name.toLowerCase(), fmt = EN ? 'binary' : 'binario';\n    function add(lbl, data) { if (data.length) out.push({ lbl: lbl, b: data }); }\n    if (isText(b)) {\n      var h = parseHex(new TextDecoder('latin1').decode(b));\n      if (h) { b = fromHex(h); fmt = h.fmt + (EN ? ' from address $' : ' dall\\'indirizzo $') + hex(h.lo, 4); }\n    }\n    add(t(UI.whole), b);\n    var s4 = String.fromCharCode.apply(null, b.subarray(0, 16));\n    if (s4.indexOf('NES\\x1a') === 0) { var tr = (b[6] & 4) ? 512 : 0, prg = b[4] * 16384, chr = b[5] * 8192; fmt = 'iNES'; add(EN ? 'NES: PRG ROM' : 'NES: PRG ROM', b.subarray(16 + tr, 16 + tr + prg)); if (chr) add(EN ? 'NES: CHR ROM' : 'NES: CHR ROM', b.subarray(16 + tr + prg, 16 + tr + prg + chr)); }\n    else if (s4.indexOf('C64 CARTRIDGE') === 0) {\n      fmt = 'C64 CRT'; var p = (b[16] << 24 | b[17] << 16 | b[18] << 8 | b[19]) >>> 0, k = 0;\n      while (p + 16 <= b.length && String.fromCharCode(b[p], b[p + 1], b[p + 2], b[p + 3]) === 'CHIP') {\n        var plen = (b[p + 4] << 24 | b[p + 5] << 16 | b[p + 6] << 8 | b[p + 7]) >>> 0, rs = b[p + 14] << 8 | b[p + 15], la = b[p + 12] << 8 | b[p + 13];\n        add('CRT CHIP ' + (k++) + ' $' + hex(la, 4), b.subarray(p + 16, p + 16 + rs)); p += plen;\n      }\n    }\n    else if (b[1] === 0x41 && String.fromCharCode.apply(null, b.subarray(1, 10)) === 'ATARI7800') { fmt = 'Atari 7800 A78'; add('A78 ROM', b.subarray(128)); }\n    else if (s4.indexOf('LYNX') === 0) { fmt = 'Atari Lynx LNX'; add('LNX ROM', b.subarray(64)); }\n    else if (b.length % 1024 === 512 && b.length > 1024) { add(EN ? 'Without 512-byte copier header' : 'Senza intestazione di 512 byte', b.subarray(512)); }\n    if (\/\\.prg$\/.test(low) && b.length > 2) add(EN ? 'Without the 2-byte load address' : 'Senza i 2 byte dell\\'indirizzo di caricamento', b.subarray(2));\n    \/\/ N64: porta i formati .v64 e .n64 all'ordine .z64\n    if (b.length >= 4 && b[0] === 0x37 && b[1] === 0x80) { fmt = 'N64 (.v64)'; add('N64 \u2192 .z64', swap16(b)); }\n    else if (b.length >= 4 && b[0] === 0x40 && b[1] === 0x12) { fmt = 'N64 (.n64)'; add('N64 \u2192 .z64', swap32(b)); }\n    if (b.length > 8388608) return { fmt: fmt, data: b, list: out };     \/\/ file grandi (giochi N64...): niente prove sulle parti\n    \/\/ contenuto ripetuto: la ROM vera e' piu' piccola\n    var u = b;\n    while (u.length >= 2048 && u.length % 2 === 0 && same(u.subarray(0, u.length \/ 2), u.subarray(u.length \/ 2))) u = u.subarray(0, u.length \/ 2);\n    if (u !== b) add((EN ? 'Repeated content: real ROM of ' : 'Contenuto ripetuto: ROM vera di ') + sizeTxt(u.length), u);\n    else if (b.length >= 4096 && (b.length & (b.length - 1)) === 0) {\n      add(EN ? 'First half' : 'Prima met\u00e0', b.subarray(0, b.length \/ 2));\n      add(EN ? 'Second half' : 'Seconda met\u00e0', b.subarray(b.length \/ 2));\n    }\n    if (b.length >= 2 && b.length % 2 === 0) {\n      add(EN ? 'Byte-swapped (16 bit)' : 'Byte scambiati (16 bit)', swap16(b));\n      add(EN ? 'Even bytes only' : 'Solo byte pari', pick(b, 0)); add(EN ? 'Odd bytes only' : 'Solo byte dispari', pick(b, 1));\n    }\n    return { fmt: fmt, data: b, list: out };\n  }\n  function same(a, c) { if (a.length !== c.length) return false; for (var i = 0; i < a.length; i++) if (a[i] !== c[i]) return false; return true; }\n  function swap16(b) { var o = new Uint8Array(b.length & ~1); for (var i = 0; i + 1 < b.length; i += 2) { o[i] = b[i + 1]; o[i + 1] = b[i]; } return o; }\n  function swap32(b) { var o = new Uint8Array(b.length & ~3); for (var i = 0; i + 3 < b.length; i += 4) { o[i] = b[i + 3]; o[i + 1] = b[i + 2]; o[i + 2] = b[i + 1]; o[i + 3] = b[i]; } return o; }\n  function pick(b, s) { var o = new Uint8Array(b.length >> 1); for (var i = 0; i < o.length; i++) o[i] = b[i * 2 + s]; return o; }\n\n  \/* ---------- controlli sul contenuto ---------- *\/\n  function checks(b) {\n    var out = [], cnt = new Uint32Array(256), or = 0, and = 255;\n    for (var i = 0; i < b.length; i++) { cnt[b[i]]++; or |= b[i]; and &= b[i]; }\n    var top = 0; for (var v = 1; v < 256; v++) if (cnt[v] > cnt[top]) top = v;\n    var st = 'ok';\n    if (!b.length) { out.push(['bad', EN ? 'Empty file.' : 'File vuoto.']); return { st: 'bad', msgs: out }; }\n    if (cnt[0xff] === b.length) { out.push(['bad', EN ? 'All bytes are FF: blank (erased) EPROM, or a chip that was not read (pins not touching, wrong chip type).' : 'Tutti i byte sono FF: EPROM vuota (cancellata) oppure chip non letto (piedini non a contatto, tipo di chip sbagliato).']); return { st: 'blank', msgs: out }; }\n    if (cnt[0] === b.length) { out.push(['bad', EN ? 'All bytes are 00: chip not powered, short on the data lines, or wrong read mode.' : 'Tutti i byte sono 00: chip non alimentato, corto sulle linee dati o modalit\u00e0 di lettura sbagliata.']); return { st: 'blank', msgs: out }; }\n    if (cnt[top] === b.length) { out.push(['bad', (EN ? 'Every byte is $' : 'Tutti i byte valgono $') + hex(top, 2) + (EN ? ': not a real dump.' : ': non \u00e8 una lettura valida.')]); return { st: 'blank', msgs: out }; }\n    var stuck = [];\n    for (var bit = 0; bit < 8; bit++) { if (!(or >> bit & 1)) stuck.push('D' + bit + (EN ? ' always 0' : ' sempre a 0')); else if (and >> bit & 1) stuck.push('D' + bit + (EN ? ' always 1' : ' sempre a 1')); }\n    if (stuck.length && b.length >= 256) { out.push(['warn', (EN ? 'Data line stuck: ' : 'Linea dati bloccata: ') + stuck.join(', ') + (EN ? '. In a real ROM every bit changes: check the chip, the socket or the programmer contact.' : '. In una ROM vera ogni bit cambia: controlla il chip, lo zoccolo o il contatto nel programmatore.')]); st = 'warn'; }\n    var ffTail = 0; for (var j = b.length - 1; j >= 0 && b[j] === 0xff; j--) ffTail++;\n    if (ffTail > b.length \/ 2) out.push(['msg', (EN ? 'The last ' : 'Gli ultimi ') + sizeTxt(ffTail) + (EN ? ' are FF (unused space, or a smaller ROM read as a bigger chip).' : ' sono FF (spazio non usato, oppure ROM pi\u00f9 piccola letta come chip pi\u00f9 grande).')]);\n    if ((b.length & (b.length - 1)) !== 0 && b.length % 1024 !== 512) { out.push(['warn', EN ? 'The size is not a power of two: it is not a whole chip (or the file has a header).' : 'La dimensione non \u00e8 una potenza di due: non \u00e8 un chip intero (o il file ha un\\'intestazione).']); if (st === 'ok') st = 'warn'; }\n    return { st: st, msgs: out };\n  }\n  \/\/ Kickstart Amiga: intestazione, versione e checksum interno\n  function kickstart(b) {\n    if (b.length < 262144 || (b.length !== 262144 && b.length !== 524288 && b.length !== 1048576)) return null;\n    var w = b, swapped = false;\n    if (w[0] === 0x11 && (w[1] === 0x14 || w[1] === 0x11) && w[2] === 0x4e && w[3] === 0xf9) {} else if (w[1] === 0x11 && (w[0] === 0x14 || w[0] === 0x11) && w[3] === 0x4e && w[2] === 0xf9) { w = swap16(b); swapped = true; } else return null;\n    var sum = 0;\n    for (var i = 0; i < w.length; i += 4) { sum += (w[i] << 24 | w[i + 1] << 16 | w[i + 2] << 8 | w[i + 3]) >>> 0; if (sum > 0xffffffff) sum -= 0xffffffff; }\n    var ver = (w[12] << 8 | w[13]) + '.' + (w[14] << 8 | w[15]);\n    return { ver: ver, ok: sum === 0xffffffff, swapped: swapped };\n  }\n  function strings(b) {\n    var out = [], cur = '';\n    for (var i = 0; i < b.length && out.length < 40; i++) { var c = b[i] & 0x7f; if (c >= 32 && c < 127) cur += String.fromCharCode(c); else { if (cur.length >= 6 && \/[A-Za-z]{3}\/.test(cur)) out.push(cur); cur = ''; } }\n    if (cur.length >= 6) out.push(cur);\n    return out.filter(function (s, i, a) { return a.indexOf(s) === i; }).slice(0, 25);\n  }\n\n  \/* ---------- analisi di un file ---------- *\/\n  function analyse(name, buf, box) {\n    var V = variants(name, new Uint8Array(buf)), b = V.data, ck = checks(b), ks = kickstart(b);\n    var head = '<div class=\"top\"><h3>' + esc(name) + '<\/h3><span class=\"badge\" id=\"' + box.id + 'B\"><span class=\"spin\"><\/span><\/span><\/div>';\n    var facts = '<div class=\"facts\"><div><small>' + t(UI.size) + '<\/small><code>' + sizeTxt(b.length) + '<\/code><\/div><div><small>' + t(UI.eprom) + '<\/small><code>' + esc(epromFor(b.length)) + '<\/code><\/div>' +\n      '<div><small>' + t(UI.fmt) + '<\/small><code>' + esc(V.fmt) + '<\/code><\/div><div><small>' + t(UI.crc) + '<\/small><code>' + crc32(b).toUpperCase() + '<\/code><\/div><div><small>' + t(UI.sha) + '<\/small><code id=\"' + box.id + 'S\">\u2026<\/code><\/div><\/div>';\n    var msgs = ck.msgs.map(function (m) { return '<div class=\"msg ' + m[0] + '\">' + esc(m[1]) + '<\/div>'; });\n    if (ks) msgs.push('<div class=\"msg ' + (ks.ok ? 'ok' : 'bad') + '\">' + esc((EN ? 'Amiga Kickstart, version ' : 'Kickstart Amiga, versione ') + ks.ver + (ks.swapped ? (EN ? ' (byte-swapped file)' : ' (file con i byte scambiati)') : '') + ': ' + (ks.ok ? (EN ? 'internal checksum correct.' : 'checksum interno corretto.') : (EN ? 'internal checksum WRONG: the dump or the ROM is damaged.' : 'checksum interno SBAGLIATO: il dump o la ROM sono rovinati.'))) + '<\/div>');\n    var str = strings(b);\n    box.innerHTML = head + facts + '<div class=\"msgs\">' + msgs.join('') + '<\/div><div id=\"' + box.id + 'M\"><p class=\"note\"><span class=\"spin\"><\/span>' + esc(t(UI.reading)) + '<\/p><\/div>' +\n      (str.length ? '<details><summary class=\"note\" style=\"cursor:pointer\">' + esc(t(UI.strings)) + '<\/summary><div class=\"strs\">' + esc(str.join('\\n')) + '<\/div><\/details>' : '');\n    sha1(b).then(function (h) { $(box.id + 'S').textContent = h ? h.toUpperCase() : '\u2014'; });\n    if (ck.st === 'blank') { setBadge(box, 'bad', UI.blank); $(box.id + 'M').innerHTML = ''; return; }\n    search(V.list, box, ck.st);\n  }\n  function search(list, box, st) {\n    var seen = {}, jobs = [];\n    list.forEach(function (v) {\n      var c = crc32(v.b); if (seen[c + v.b.length]) return; seen[c + v.b.length] = 1;\n      jobs.push(lookup(c, v.b.length).then(function (r) { return { v: v, crc: c, r: r }; }));\n    });\n    Promise.all(jobs).then(function (res) {\n      var hits = res.filter(function (x) { return x.r.length; });\n      if (!hits.length) { setBadge(box, st === 'warn' ? 'warn' : 'unk', st === 'warn' ? UI.suspect : UI.notfound); $(box.id + 'M').innerHTML = '<div class=\"msg\">' + esc(t(UI.nomatch)) + '<\/div>'; return; }\n      setBadge(box, 'ok', UI.found);\n      return Promise.all(hits.map(function (x) { return sha1(x.v.b).then(function (h) { x.sha = h; return x; }); })).then(function (hs) {\n        $(box.id + 'M').innerHTML = hs.map(function (x) {\n          return x.r.map(function (e) {\n            var conf = x.sha ? (x.sha.indexOf(e.sha) === 0 ? '\u2713 ' + t(UI.sha1ok) : '\u26a0 ' + t(UI.sha1no)) : '';\n            var ms = e.machines.map(function (m) { return '<li>' + esc(m.d) + ' <small>(' + esc([m.y, m.m].filter(Boolean).concat([m.n]).join(' \u00b7 ')) + ')<\/small><span class=\"kind\">' + esc(t(KINDS[m.k] || ['', ''])) + '<\/span><\/li>'; }).join('');\n            return '<div class=\"match\"><h4>' + esc(e.names.split(',').join(', ')) + '<\/h4><div class=\"how\">' + esc(x.v.lbl) + ' \u00b7 CRC ' + x.crc.toUpperCase() + ' \u00b7 ' + sizeTxt(e.size) + (conf ? ' \u00b7 ' + esc(conf) : '') + '<\/div><ul>' + ms + '<\/ul>' +\n              (e.count > e.machines.length ? '<div class=\"how\">' + esc(t(UI.usedin) + ' ' + e.count + ' ' + t(UI.machines) + ' (' + t(UI.andmore) + ')') + '<\/div>' : '') + '<\/div>';\n          }).join('');\n        }).join('');\n      });\n    }).catch(function () { setBadge(box, 'warn', UI.notfound); $(box.id + 'M').innerHTML = '<div class=\"msg bad\">' + esc(t(UI.dberr)) + '<\/div>'; });\n  }\n  function setBadge(box, cls, lbl) { var e = $(box.id + 'B'); e.className = 'badge ' + cls; e.textContent = t(lbl); }\n\n  var nbox = 0;\n  function handle(files) {\n    files = [].slice.call(files);\n    $('rfriOut').innerHTML = '';\n    var bufs = [];\n    files.forEach(function (f) {\n      var box = document.createElement('div'); box.className = 'file'; box.id = 'rfriF' + (nbox++); $('rfriOut').appendChild(box);\n      var p = f.arrayBuffer().then(function (buf) { analyse(f.name, buf, box); return { name: f.name, b: new Uint8Array(buf) }; });\n      bufs.push(p);\n    });\n    \/\/ due file della stessa dimensione: prova a unirli (pari\/dispari e uno dopo l'altro)\n    if (files.length === 2) Promise.all(bufs).then(function (x) {\n      if (x[0].b.length !== x[1].b.length) return;\n      var n = x[0].b.length, il = new Uint8Array(n * 2), il2 = new Uint8Array(n * 2), cat = new Uint8Array(n * 2);\n      for (var i = 0; i < n; i++) { il[i * 2] = x[0].b[i]; il[i * 2 + 1] = x[1].b[i]; il2[i * 2] = x[1].b[i]; il2[i * 2 + 1] = x[0].b[i]; }\n      cat.set(x[0].b); cat.set(x[1].b, n);\n      var box = document.createElement('div'); box.className = 'file'; box.id = 'rfriF' + (nbox++); $('rfriOut').appendChild(box);\n      box.innerHTML = '<div class=\"top\"><h3>' + esc(t(UI.pair)) + ': ' + esc(x[0].name) + ' + ' + esc(x[1].name) + '<\/h3><span class=\"badge\" id=\"' + box.id + 'B\"><span class=\"spin\"><\/span><\/span><\/div><div id=\"' + box.id + 'M\"><\/div>';\n      search([{ lbl: EN ? 'Interleaved (first = even bytes)' : 'Alternati (il primo = byte pari)', b: il }, { lbl: EN ? 'Interleaved (first = odd bytes)' : 'Alternati (il primo = byte dispari)', b: il2 }, { lbl: EN ? 'One after the other' : 'Uno dopo l\\'altro', b: cat }], box, 'ok');\n    });\n  }\n  var drop = $('rfriDrop'), inp = $('rfriIn');\n  inp.addEventListener('change', function () { if (inp.files.length) handle(inp.files); inp.value = ''; });\n  ['dragenter', 'dragover'].forEach(function (ev) { drop.addEventListener(ev, function (e) { e.preventDefault(); drop.classList.add('over'); }); });\n  ['dragleave', 'drop'].forEach(function (ev) { drop.addEventListener(ev, function (e) { e.preventDefault(); drop.classList.remove('over'); }); });\n  drop.addEventListener('drop', function (e) { if (e.dataTransfer.files.length) handle(e.dataTransfer.files); });\n  root._test = handle;\n})();\n<\/script>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-11758","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/retrofixer.it\/en\/wp-json\/wp\/v2\/pages\/11758","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/retrofixer.it\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/retrofixer.it\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/retrofixer.it\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/retrofixer.it\/en\/wp-json\/wp\/v2\/comments?post=11758"}],"version-history":[{"count":6,"href":"https:\/\/retrofixer.it\/en\/wp-json\/wp\/v2\/pages\/11758\/revisions"}],"predecessor-version":[{"id":11764,"href":"https:\/\/retrofixer.it\/en\/wp-json\/wp\/v2\/pages\/11758\/revisions\/11764"}],"wp:attachment":[{"href":"https:\/\/retrofixer.it\/en\/wp-json\/wp\/v2\/media?parent=11758"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/retrofixer.it\/en\/wp-json\/wp\/v2\/categories?post=11758"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/retrofixer.it\/en\/wp-json\/wp\/v2\/tags?post=11758"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}