mirror of
https://github.com/transistorfet/moa.git
synced 2024-10-31 19:04:37 +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)
|
(((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_addr = (pattern_name & 0x07FF) << 5;
|
||||||
let pattern_palette = ((pattern_name & 0x6000) >> 13) as u8;
|
let pattern_palette = ((pattern_name & 0x6000) >> 13) as u8;
|
||||||
let h_rev = (pattern_name & 0x0800) != 0;
|
let h_rev = (pattern_name & 0x0800) != 0;
|
||||||
let v_rev = (pattern_name & 0x1000) != 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 {
|
let base_addr = match self.mode_3 & MODE3_BF_H_SCROLL_MODE {
|
||||||
0 => self.hscroll_addr,
|
0 => self.hscroll_addr,
|
||||||
2 => self.hscroll_addr + (hcell << 4),
|
2 => self.hscroll_addr + (hcell << 4),
|
||||||
@ -329,8 +329,9 @@ impl Ym7101State {
|
|||||||
_ => panic!("Unsupported horizontal scroll mode"),
|
_ => panic!("Unsupported horizontal scroll mode"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let scroll_a = read_beu16(&self.vram[base_addr..]) as u32 & 0x3FF;
|
let scroll_addr = base_addr + (column * 2 * 2);
|
||||||
let scroll_b = read_beu16(&self.vram[base_addr + 2..]) as u32 & 0x3FF;
|
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)
|
(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) {
|
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);
|
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) {
|
pub fn draw_frame(&mut self, frame: &mut Frame) {
|
||||||
self.draw_background(frame);
|
self.draw_background(frame);
|
||||||
self.draw_scrolls(frame);
|
self.draw_scrolls(frame);
|
||||||
@ -383,25 +389,61 @@ impl Ym7101State {
|
|||||||
frame.clear(bg_colour);
|
frame.clear(bg_colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
pub fn draw_scrolls(&mut self, frame: &mut Frame) {
|
pub fn draw_scrolls(&mut self, frame: &mut Frame) {
|
||||||
let (scroll_h, scroll_v) = self.scroll_size;
|
if (self.mode_3 & MODE3_BF_H_SCROLL_MODE) != 3 {
|
||||||
let (cells_h, cells_v) = self.screen_size;
|
self.draw_scrolls_cell(frame);
|
||||||
|
} else {
|
||||||
if scroll_h == 0 || scroll_v == 0 {
|
self.draw_scrolls_line(frame);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
for cell_y in 0..cells_v {
|
||||||
let (vscrolling_a, vscrolling_b) = self.get_vscroll(cell_y);
|
let (vscrolling_a, vscrolling_b) = self.get_vscroll(cell_y);
|
||||||
for cell_x in 0..cells_h {
|
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_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);
|
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 {
|
//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_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);
|
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 (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);
|
let (x, y) = (h_pos + ih * 8, v_pos + iv * 8);
|
||||||
if x > 128 && x < pos_limit_h && y > 128 && y < pos_limit_v {
|
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);
|
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> {
|
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 {
|
Self {
|
||||||
state,
|
state,
|
||||||
palette,
|
palette,
|
||||||
base: start as usize,
|
base: start as usize,
|
||||||
h_rev,
|
h_rev,
|
||||||
v_rev,
|
v_rev,
|
||||||
line: 0,
|
line,
|
||||||
col: 0,
|
col: 0,
|
||||||
second: false,
|
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:
|
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?
|
* how can you improve the debugger?
|
||||||
* the command line definitely needs to be fixed so it prints the prompt correctly
|
* 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
|
* debugger could maybe even allows arrows left/right for editing, and up/down for history
|
||||||
@ -66,7 +79,6 @@ Macintosh:
|
|||||||
|
|
||||||
68000:
|
68000:
|
||||||
|
|
||||||
* add instruction timing to M68k
|
|
||||||
* check all instructions in the docs
|
* check all instructions in the docs
|
||||||
|
|
||||||
* unimplemented: BFFFO, BFINS, CHK, ILLEGAL, NBCD, NEGX, RTR, RTD
|
* unimplemented: BFFFO, BFINS, CHK, ILLEGAL, NBCD, NEGX, RTR, RTD
|
||||||
|
Loading…
Reference in New Issue
Block a user