mirror of
https://github.com/koute/pinky.git
synced 2025-04-02 10:31:50 -04:00
207 lines
8.2 KiB
JavaScript
207 lines
8.2 KiB
JavaScript
"use strict";
|
|
|
|
var fs = require( "fs" );
|
|
var phantom2c02 = require( "./phantom2c02/phantom2c02" );
|
|
var _ = require( "./phantom2c02/lib/lodash" );
|
|
var sprintf = require( "./phantom2c02/lib/sprintf" ).sprintf;
|
|
|
|
function generate( name, callback ) {
|
|
phantom2c02.create( function( ctx ) {
|
|
var output = "";
|
|
var automatically_output_code = true;
|
|
|
|
var disable_automatic_code_output = function( callback ) {
|
|
var previous = automatically_output_code;
|
|
automatically_output_code = false;
|
|
var result = callback();
|
|
automatically_output_code = previous;
|
|
|
|
return result;
|
|
};
|
|
|
|
var indent = function( callback ) {
|
|
self.indentation += 4;
|
|
callback();
|
|
self.indentation -= 4;
|
|
};
|
|
|
|
var output_loop = function( times, callback, extra_args ) {
|
|
extra_args = extra_args || {};
|
|
|
|
self.println( "for %s in 0..%iu32 {", extra_args.variable || "i", times );
|
|
indent( callback );
|
|
|
|
if( extra_args.output_position === true ) {
|
|
self.println( "} // %s -> %s", ctx.get_position().add( -1 ), ctx.get_position() );
|
|
} else {
|
|
self.println( "}" );
|
|
}
|
|
};
|
|
|
|
var self = {
|
|
indentation: 0,
|
|
|
|
println: function() {
|
|
var args = Array.prototype.slice.call( arguments );
|
|
var line = sprintf.apply( null, args );
|
|
self.repeat( self.indentation, function() {
|
|
output += " ";
|
|
});
|
|
output += line;
|
|
output += "\n";
|
|
},
|
|
|
|
step_pixel: ctx.step_pixel,
|
|
step_scanline: ctx.step_scanline,
|
|
cpu_write_and_step: ctx.cpu_write_and_step,
|
|
write_oam: ctx.write_oam,
|
|
write_sprite_to_oam: ctx.write_sprite_to_oam,
|
|
write_secondary_oam: ctx.write_secondary_oam,
|
|
write_sprite_to_secondary_oam: ctx.write_sprite_to_secondary_oam,
|
|
write_palette_ram: ctx.write_palette_ram,
|
|
write_vram: ctx.write_vram,
|
|
|
|
test: {
|
|
next_vram_read: function() {
|
|
if( ctx.is_reading_from_vram() ) {
|
|
self.println( "ppu.expect_vram_read( 0x%04X, 0x%02X );", ctx.get_address_bus(), ctx.get_data_bus() );
|
|
} else {
|
|
self.println( "ppu.expect_no_vram_read();" );
|
|
}
|
|
},
|
|
|
|
current_address: function() {
|
|
self.println( "assert_eq( ppu.get_current_address(), 0x%04X );", ctx.get_current_address() );
|
|
},
|
|
|
|
temporary_address: function() {
|
|
self.println( "assert_eq( ppu.get_temporary_address(), 0x%04X );", ctx.get_temporary_address() );
|
|
},
|
|
|
|
cpu_read: function( address ) {
|
|
var obj = ctx.resolve_io_port( address );
|
|
ctx.queue_cpu_read( obj, function( value ) {
|
|
self.println( "assert_eq( ppu.read_ioreg( %i ), 0x%02X );", (obj.address - 0x2000) & (8 - 1), value );
|
|
});
|
|
},
|
|
|
|
secondary_oam_contents: function() {
|
|
_.each( ctx.dump_secondary_oam(), function( value, index ) {
|
|
self.println( "assert_eq( ppu.read_secondary_sprite_ram( %i ), 0x%02X );", index, value );
|
|
});
|
|
}
|
|
},
|
|
|
|
fill_vram_with_test_data: function() {
|
|
disable_automatic_code_output( function() {
|
|
// Fill out the first pattern table.
|
|
self.repeat( 0x1000, function( addr ) {
|
|
self.write_vram( addr, (addr + 0x80) & 0xFF );
|
|
});
|
|
|
|
// Fill out the first nametable.
|
|
self.repeat( 960, function( offset ) {
|
|
self.write_vram( 0x2000 + offset, (offset + 0x80) & 0xFF );
|
|
});
|
|
|
|
// Fill out the first attribute table.
|
|
self.repeat( 64, function( offset ) {
|
|
self.write_vram( 0x2000 + 960 + offset, 0x80 | offset );
|
|
});
|
|
});
|
|
|
|
output_loop( 0x1000, function() {
|
|
self.println( "ppu.write_vram( i as u16, (i + 0x80) as u8 );" );
|
|
});
|
|
|
|
output_loop( 960, function() {
|
|
self.println( "ppu.write_vram( (0x2000 + i) as u16, (i + 0x80) as u8 );" );
|
|
});
|
|
|
|
output_loop( 64, function() {
|
|
self.println( "ppu.write_vram( (0x2000 + 960 + i) as u16, (0x80 | i) as u8 );" );
|
|
});
|
|
},
|
|
|
|
repeat: function( times, callback ) {
|
|
if( callback === ctx.step_pixel ) {
|
|
disable_automatic_code_output( function() {
|
|
ctx.repeat( times, callback );
|
|
output_loop( times, _.partial( self.println, "ppu.step_pixel();" ), { output_position: true, variable: "_" } );
|
|
});
|
|
} else if( callback === ctx.step_scanline ) {
|
|
disable_automatic_code_output( function() {
|
|
ctx.repeat( times, callback );
|
|
output_loop( times, _.partial( self.println, "ppu.step_scanline();" ), { output_position: true, variable: "_" } );
|
|
});
|
|
} else {
|
|
ctx.repeat( times, callback );
|
|
}
|
|
},
|
|
|
|
simulator: ctx
|
|
};
|
|
|
|
ctx.on_write_vram_called = function( address, value ) {
|
|
if( !automatically_output_code ) return;
|
|
self.println( "ppu.write_vram( 0x%04X, 0x%02X );", address, value );
|
|
};
|
|
|
|
ctx.on_write_palette_ram_called = function( offset, value ) {
|
|
if( !automatically_output_code ) return;
|
|
self.println( "ppu.write_palette_ram( %i, 0x%02X );", offset, value );
|
|
};
|
|
|
|
ctx.on_write_oam_called = function( offset, value ) {
|
|
if( !automatically_output_code ) return;
|
|
self.println( "ppu.write_sprite_ram( %i, 0x%02X );", offset, value );
|
|
};
|
|
|
|
ctx.on_write_secondary_oam_called = function( offset, value ) {
|
|
if( !automatically_output_code ) return;
|
|
self.println( "ppu.write_secondary_sprite_ram( %i, 0x%02X );", offset, value );
|
|
};
|
|
|
|
ctx.on_cpu_write_called = function( address, value ) {
|
|
if( !automatically_output_code ) return;
|
|
self.println( "ppu.write_ioreg( %i, 0x%02X );", (address - 0x2000) & (8 - 1), value );
|
|
};
|
|
|
|
ctx.on_step_pixel_called = function() {
|
|
if( !automatically_output_code ) return;
|
|
self.println( "ppu.step_pixel(); // %s -> %s", ctx.get_position().add( -1 ), ctx.get_position() );
|
|
};
|
|
|
|
ctx.on_step_scanline_called = function() {
|
|
if( !automatically_output_code ) return;
|
|
self.println( "ppu.step_scanline();" );
|
|
};
|
|
|
|
console.log( "Generating '" + name + "'..." );
|
|
|
|
self.println( "// This file was AUTOGENERATED; do not edit!" );
|
|
self.println( "" );
|
|
self.println( "#[allow(unused_imports)]" );
|
|
self.println( "use super::super::assert_eq;" );
|
|
self.println( "use TestPPU;" );
|
|
self.println( "" );
|
|
self.println( "#[inline(never)]" );
|
|
self.println( "pub fn test_" + name + "( ppu: &mut TestPPU ) {" );
|
|
self.indentation += 4;
|
|
self.println( "assert_eq!( ppu.scanline(), %s );", ctx.get_scanline() );
|
|
self.println( "assert_eq!( ppu.dot(), %s );", ctx.get_dot() );
|
|
callback( self );
|
|
self.println( "assert_eq!( ppu.scanline(), %s );", ctx.get_scanline() );
|
|
self.println( "assert_eq!( ppu.dot(), %s );", ctx.get_dot() );
|
|
self.indentation -= 4;
|
|
self.println( "}" );
|
|
|
|
fs.write( module.dirname + "/../src/tests/test_" + name + ".rs", output );
|
|
ctx.exit();
|
|
});
|
|
}
|
|
|
|
module.exports.generate = generate;
|
|
module.exports.ppumask = phantom2c02.ppumask;
|
|
module.exports.ppuctrl = phantom2c02.ppuctrl;
|
|
module.exports.sprite = phantom2c02.sprite;
|