mirror of
https://github.com/transistorfet/moa.git
synced 2024-11-25 15:33:08 +00:00
Added line-based hscroll and fixed an hscroll bug
The hscroll table was multiplying by 2 (because scroll a and b values are next to each other) but it should have multiplied by 4 because each value is also 2 bytes and the array is of u8. I added hscroll by-line support by using a different function for the line scroll vs the cell or whole screen scrolling. There are still a bunch of glitches in scroll b's scroll values that I need to fix
This commit is contained in:
parent
4ca0c9b625
commit
18e54f4a44
@ -313,15 +313,15 @@ impl Ym7101State {
|
||||
(((rgb & 0xF00) as u32) >> 4) | (((rgb & 0x0F0) as u32) << 8) | (((rgb & 0x00F) as u32) << 20)
|
||||
}
|
||||
|
||||
pub fn get_pattern_iter<'a>(&'a self, pattern_name: u16) -> PatternIterator<'a> {
|
||||
pub fn get_pattern_iter<'a>(&'a self, pattern_name: u16, line: i8) -> PatternIterator<'a> {
|
||||
let pattern_addr = (pattern_name & 0x07FF) << 5;
|
||||
let pattern_palette = ((pattern_name & 0x6000) >> 13) as u8;
|
||||
let h_rev = (pattern_name & 0x0800) != 0;
|
||||
let v_rev = (pattern_name & 0x1000) != 0;
|
||||
PatternIterator::new(&self, pattern_addr as u32, pattern_palette, h_rev, v_rev)
|
||||
PatternIterator::new(&self, pattern_addr as u32, pattern_palette, h_rev, v_rev, line)
|
||||
}
|
||||
|
||||
pub fn get_hscroll(&self, hcell: usize) -> (u32, u32) {
|
||||
pub fn get_hscroll(&self, hcell: usize, column: usize) -> (u32, u32) {
|
||||
let base_addr = match self.mode_3 & MODE3_BF_H_SCROLL_MODE {
|
||||
0 => self.hscroll_addr,
|
||||
2 => self.hscroll_addr + (hcell << 4),
|
||||
@ -329,8 +329,9 @@ impl Ym7101State {
|
||||
_ => panic!("Unsupported horizontal scroll mode"),
|
||||
};
|
||||
|
||||
let scroll_a = read_beu16(&self.vram[base_addr..]) as u32 & 0x3FF;
|
||||
let scroll_b = read_beu16(&self.vram[base_addr + 2..]) as u32 & 0x3FF;
|
||||
let scroll_addr = base_addr + (column * 2 * 2);
|
||||
let scroll_a = read_beu16(&self.vram[scroll_addr..]) as u32 & 0x3FF;
|
||||
let scroll_b = read_beu16(&self.vram[scroll_addr + 2..]) as u32 & 0x3FF;
|
||||
(scroll_a, scroll_b)
|
||||
}
|
||||
|
||||
@ -367,10 +368,15 @@ impl Ym7101State {
|
||||
|
||||
|
||||
pub fn draw_pattern(&mut self, frame: &mut Frame, pattern: u16, pixel_x: u32, pixel_y: u32) {
|
||||
let iter = self.get_pattern_iter(pattern);
|
||||
let iter = self.get_pattern_iter(pattern, 0);
|
||||
frame.blit(pixel_x, pixel_y, iter, 8, 8);
|
||||
}
|
||||
|
||||
pub fn draw_pattern_line(&mut self, frame: &mut Frame, pattern: u16, pixel_x: u32, pixel_y: u32, line: i8) {
|
||||
let iter = self.get_pattern_iter(pattern, line);
|
||||
frame.blit(pixel_x, pixel_y, iter, 8, 1);
|
||||
}
|
||||
|
||||
pub fn draw_frame(&mut self, frame: &mut Frame) {
|
||||
self.draw_background(frame);
|
||||
self.draw_scrolls(frame);
|
||||
@ -383,25 +389,61 @@ impl Ym7101State {
|
||||
frame.clear(bg_colour);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn draw_scrolls(&mut self, frame: &mut Frame) {
|
||||
let (scroll_h, scroll_v) = self.scroll_size;
|
||||
let (cells_h, cells_v) = self.screen_size;
|
||||
|
||||
if scroll_h == 0 || scroll_v == 0 {
|
||||
return;
|
||||
if (self.mode_3 & MODE3_BF_H_SCROLL_MODE) != 3 {
|
||||
self.draw_scrolls_cell(frame);
|
||||
} else {
|
||||
self.draw_scrolls_line(frame);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_scrolls_cell(&mut self, frame: &mut Frame) {
|
||||
let (cells_h, cells_v) = self.screen_size;
|
||||
|
||||
for cell_y in 0..cells_v {
|
||||
let (vscrolling_a, vscrolling_b) = self.get_vscroll(cell_y);
|
||||
for cell_x in 0..cells_h {
|
||||
let (hscrolling_a, hscrolling_b) = self.get_hscroll(cell_x);
|
||||
let (hscrolling_a, hscrolling_b) = self.get_hscroll(cell_x, 0);
|
||||
|
||||
let pattern_b = self.get_scroll_b_pattern(cell_x, cell_y, hscrolling_b as usize, vscrolling_b as usize);
|
||||
let pattern_a = self.get_scroll_a_pattern(cell_x, cell_y, hscrolling_a as usize, vscrolling_a as usize);
|
||||
|
||||
//if (pattern_b & 0x8000) != 0 && (pattern_a & 0x8000) == 0 {
|
||||
self.draw_pattern(frame, pattern_b, (cell_x << 3) as u32, (cell_y << 3) as u32);
|
||||
self.draw_pattern(frame, pattern_a, (cell_x << 3) as u32, (cell_y << 3) as u32);
|
||||
self.draw_pattern(frame, pattern_b, (cell_x << 3) as u32, (cell_y << 3) as u32 - (vscrolling_b % 8));
|
||||
self.draw_pattern(frame, pattern_a, (cell_x << 3) as u32, (cell_y << 3) as u32 - (vscrolling_b % 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_scrolls_line(&mut self, frame: &mut Frame) {
|
||||
let (cells_h, cells_v) = self.screen_size;
|
||||
|
||||
for cell_y in 0..cells_v {
|
||||
let (vscrolling_a, vscrolling_b) = self.get_vscroll(cell_y);
|
||||
for cell_x in 0..cells_h {
|
||||
let (hscrolling_a, hscrolling_b) = self.get_hscroll(cell_x, 0);
|
||||
|
||||
let pattern_b = self.get_scroll_b_pattern(cell_x, cell_y, hscrolling_b as usize, vscrolling_b as usize);
|
||||
|
||||
for line in 0..8 {
|
||||
let (_, offset_b) = self.get_hscroll(cell_x, line as usize);
|
||||
self.draw_pattern_line(frame, pattern_b, (cell_x << 3) as u32 + (offset_b % 8), (cell_y << 3) as u32 + line as u32 - (vscrolling_b % 8), line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for cell_y in 0..cells_v {
|
||||
let (vscrolling_a, vscrolling_b) = self.get_vscroll(cell_y);
|
||||
for cell_x in 0..cells_h {
|
||||
let (hscrolling_a, hscrolling_b) = self.get_hscroll(cell_x, 0);
|
||||
|
||||
let pattern_a = self.get_scroll_a_pattern(cell_x, cell_y, hscrolling_a as usize, vscrolling_a as usize);
|
||||
|
||||
for line in 0..8 {
|
||||
let (offset_a, _) = self.get_hscroll(cell_x, line as usize);
|
||||
self.draw_pattern_line(frame, pattern_a, (cell_x << 3) as u32 + (offset_a % 8), (cell_y << 3) as u32 + line as u32 - (vscrolling_a % 8), line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -462,7 +504,7 @@ impl Ym7101State {
|
||||
let (h, v) = (if !h_rev { ih } else { size_h - 1 - ih }, if !v_rev { iv } else { size_v - 1 - iv });
|
||||
let (x, y) = (h_pos + ih * 8, v_pos + iv * 8);
|
||||
if x > 128 && x < pos_limit_h && y > 128 && y < pos_limit_v {
|
||||
let iter = self.get_pattern_iter(((pattern_name & 0x07FF) + (h * size_v) + v) | (pattern_name & 0xF800));
|
||||
let iter = self.get_pattern_iter(((pattern_name & 0x07FF) + (h * size_v) + v) | (pattern_name & 0xF800), 0);
|
||||
|
||||
frame.blit(x as u32 - 128, y as u32 - 128, iter, 8, 8);
|
||||
}
|
||||
@ -493,14 +535,14 @@ pub struct PatternIterator<'a> {
|
||||
}
|
||||
|
||||
impl<'a> PatternIterator<'a> {
|
||||
pub fn new(state: &'a Ym7101State, start: u32, palette: u8, h_rev: bool, v_rev: bool) -> Self {
|
||||
pub fn new(state: &'a Ym7101State, start: u32, palette: u8, h_rev: bool, v_rev: bool, line: i8) -> Self {
|
||||
Self {
|
||||
state,
|
||||
palette,
|
||||
base: start as usize,
|
||||
h_rev,
|
||||
v_rev,
|
||||
line: 0,
|
||||
line,
|
||||
col: 0,
|
||||
second: false,
|
||||
}
|
||||
|
16
todo.txt
16
todo.txt
@ -1,5 +1,17 @@
|
||||
|
||||
* when a MOVE's targets are both ARegDec, the 2 extra clocks can be combined (-2 clocks in this one case)
|
||||
* there is possibly a cpu bug in causing the acceleration in sonic 2 to be very slow. Speeding up the CPU makes it playably fast, but I think it's still
|
||||
incorrect, in that the top speed is faster than it should be, but the acceleration is correct...
|
||||
* for the speed problem, I've actually noticed the level vint is only called every ~33_200_000 ns which is twice as long as it should be, so maybe there's
|
||||
a vint problem, maybe even a toggle trigger that should be a one-shot
|
||||
* there is definitely something related to interrupts; 2 interrupts occur in between each call to Vint_Level (ie. Vint_Level only runs every 2 frames (33.2ms) instead
|
||||
of every frame (16.6 ms), which perfectly explains the slowdown without it being related to an instruction implementation error... but why is this happening?
|
||||
Maybe it's because the clock advances too much and first interrupt doesn't complete, or maybe there's a problem with interrupts and masking...
|
||||
It does appear to do I/O with the VDP between te interrupts so it doesn't seem to be just waiting around
|
||||
|
||||
* for the line based hscroll, you need to add that extra cell cycle...
|
||||
* there is still some kind of hscroll glitch, and it seems to entirely be caused by the horizontal scroll offset value. I could be calculating or adding/moding
|
||||
it incorrectly somewhere somehow, or the data in the hscroll table could be incorrect due to the cpu impl
|
||||
* go through the testcases and make sure they are decoded correctly
|
||||
|
||||
|
||||
|
||||
@ -40,6 +52,7 @@ Audio:
|
||||
|
||||
Debugger:
|
||||
|
||||
* i need a way to debug only the cpu and not the coprocessor, but that's tricky without a way to id or compare Transmutables
|
||||
* how can you improve the debugger?
|
||||
* the command line definitely needs to be fixed so it prints the prompt correctly
|
||||
* debugger could maybe even allows arrows left/right for editing, and up/down for history
|
||||
@ -66,7 +79,6 @@ Macintosh:
|
||||
|
||||
68000:
|
||||
|
||||
* add instruction timing to M68k
|
||||
* check all instructions in the docs
|
||||
|
||||
* unimplemented: BFFFO, BFINS, CHK, ILLEGAL, NBCD, NEGX, RTR, RTD
|
||||
|
Loading…
Reference in New Issue
Block a user