#Sega Dreamcast
1 messages · Page 4 of 1
The STV core isnt a working core its a highly experimental core and short of ElectronAsh using it its not for the general public. Its certainly not at a state where people should be testing it or even expecting it to function
Sorry, I was asleep. lol
Anyone is free to try the core, of course, but yeah - it's not running many games yet, and it often crashes.
It's very important to point out that it's still essentially Srg320's Saturn core.
Like 99.999%.
I just added some tweaks to get it to load some ST-V games as Carts.
@inland valve I don't believe I got sasissu to run at all. I think it always gave a black screen.
The same thing happens with games like Die Hard.
For some games, you have to use the "matching" BIOS. ie. the BIOS that MAME loads for the game by default.
yeah, this is probably beyond 99.9% of users to get working. and even then you're probably not going to be doing much actual game playing
Most of the games are Japan region, of course.
With the stvbios.zip that I have on MAME, it almost always uses the epr-23603.ic8.bin BIOS for Japan-region games.
But I've had more luck getting games to start, when using the stv1061 "test" BIOS.
Some games like Die Hard are USA region, and I think MAME chose epr-17952a.ic8.bin for that.
(I had to add the .bin to the end of the filename, so the MiSTer OSD doesn't hide them.)
But I only had Die Hard displaying the "Winners don't do drugs" screen, and then it would black screen again.
Even if I game might run, many games seem to need you to Clear the Backup RAM first.
That can be done in the Service menu...
Sounds like you did drugs 
Sometimes I wish. lol
Did you mamage to coin up some games or still works needs to be done ?
I think I had Guardian Force coining-up, but I'll confirm in a sec.
Joystick mapping...
(joystick_0, meaning Player 1.)
joystick_0[0] = Right
joystick_0[1] = Left
joystick_0[2] = Down
joystick_0[3] = Up
joystick_0[4] = Saturn A -> ST-V B1.
joystick_0[5] = Saturn B -> ST-V B2.
joystick_0[6] = Saturn C -> ST-V B3.
joystick_0[7] = Saturn Start -> ST-V B4.
Then the upper bits of joystick_0...
joystick_0[8] = Saturn R -> ST-V Coin 1.
joystick_0[9] = Saturn X -> ST-V Coin 2.
joystick_0[10] = Saturn Y -> ST-V TEST? AKA "Service (no toggle)"
joystick_0[11] = Saturn Z -> ST-V Service 1.
joystick_0[12] = Saturn L -> ST-V Start P1.
joystick_0[13] = ST-V Start P2.
joystick_0[14] = ST-V Multi-Cart select?
joystick_0[15] = ST-V Pause.
So, some of the normal Saturn buttons get mapped to ST-V.
Then I added a few extra buttons to the CONF_STR, so those can be mapped via the MiSTer OSD as well.
Some games seem to use Player 4 as "kick" inputs, and some might even put Start 1 and Start 2 on those buttons.
Quite a few games use a specific decryption chip, and won't Coin-up without that.
That chip hasn't been implemented / added to the core yet, and it's VERY complex.
So I wouldn't expect many games to actually be playable yet, even if they do boot.
Most games won't run either, unless you set up the Assignments menu correctly...
ie. The Cabinet Type (number of Players) needs to be correct for what the game wants.
And the Alone/Multi (multi-cart) option has to be correct.
If those are set correctly, it will generally show the game name here...
The "Each Game Test" also triggers the game's own built-in Test menu, which is separate from the ST-V BIOS test menu.
But... none of the settings for those menus are saved in the core yet.
So you usually have to set them EVERY time, and remember to do the Backup Data Clear thing.
Clearing the backup data often gets certain games to boot, but you won't necessarily be able to play them. lol
So yeah, it's very rough atm. I don't know if I'll get much time to spend on it, and I think it could be hard to debug.
Ideally, we should ask Sergey (Srg320) if he has time to take a look at it.
That's if he's not busy, of course, and not trying to survive a literal warzone. 😦
This is what I did to create the sasissu "Cart" ROM, but the game didn't boot for me anyway...
#1315008851874938948 message
The MAME code isn't super clear on how the ROMs get loaded, so I might be doing that wrong, too.
@frosty dove All of the above. lol
Thanks.
It's exciting, apologies if I got a little too far ahead of myself.
I did point out it's an early WIP. People love seeing early stuff, it definitely gets us all to appreciate all the hard work everyone does.
I also credited srg in the video.
Thanks.
I also added Jotego's 93C46 core for the EEPROM stuff.
Which I think got a few more games to boot, but it doesn't save the contents of the EEPROM either atm.
And I've only tried about six games total.
It's a bit painful to manually merge the MAME ROMs for this atm.
Until the core gets proper MRA support, and... actually plays some games. lol
I just tested Guardian Force again, with the stv1061 BIOS, but it won't let you Coin-Up.
It won't even let you use the game's own Test menu (activated via the BIOS Test menu -> EACH GAME TEST option).
When trying the Japan BIOS with the game, it then shows this…
So yeah, some games need the correct BIOS, but also the correct Assignment Settings, and they need the Backup RAM to be cleared, every single time you load a new Cart ROM.
Nope, can't hit Start.
Radient Silvergun definitely won't be playable atm. It won't let you hit Start either, as it uses the protection IC.
I've found the solution!
I had to patch the BIOS by byte-swapping it, just like the game ROMs:
dd if=stv1061.bin of=boot.rom conv=swab
At first, I thought I'd only have to patch the game ROMs !
The arcade games designers were SO untrusting back in the day. lol
Oh yeah, probably need to Byteswap the BIOS, too.
Usually that means the SEGA strings will show as "cleartext", in a Hex editor...
Original stv1061 BIOS from MAME (wrong)...
Byteswapped (correct for trying with the core)...
You must also add .bin to the end of the filename, else the MiSTer OSD will hide the files from the list.
Looking at the very few Cart ROMs I have on MiSTer, I don't remember any that were actually playable now, aside from Wack-a-poo Safari. lol
But even with that game, I don't think the "Winch" input worked, which is kind of important.
Nope, can't Coin-Up on Cotton Boomerang either.
I don't think there's too much point showing this core (well, "patch") until it's further along.
Thank you for the test
Oh, btw, the core will still show the start-up screen when using the Saturn BIOS, but it won't boot Saturn any further.
Since I disabled the CD stuff, to free up some logic for testing ST-V.
Both Cotton 2 and Cotton BM crash, if you try hitting the Test button on the title screen.
And if you launch the game's Test menu from the BIOS Test menu, it won't let you move the cursor either.
Yes the de10nano doesn't have the space to handle both 'regarding the. Space used by the Saturn core
If that can be fixed, I think more games would be playable.
It might possibly have enough space for both, if some of the "quality of life" features of the Saturn core were disabled.
But yes, it might be best to keep ST-V separate?
I don't think I've had a single "3D" game booting yet.
Peoples don't like if we remove feature already present 🤣
Exactly.
Just trying Safari, and the first two Buttons work OK (in the game's own Test menu), but not the Winch.
So yeah, sometimes hard to even find in the MAME code how some buttons are mapped, and which Port / connector they use.
ShienRyu is playable!
Using the Japan BIOS.
But only if you correctly Clear the BACKUP RAM every time.
Both in the BIOS Test menu, and in the game's Test menu.
(game Test menu activated from "EACH GAME TEST" in the BIOS menu.)
I don't think the Saturn core had the arcade-rotate option. lol
...and sometimes the game crashes, like after you lose a life, and it tries to load more data.
I'm not a huge fan of shooters. I'm terrible at them, even on Easy. lol
I think Diddy Kong Racing is more my level.
Apologies if anyone sees my moobs in the reflection, btw.
Sega 315-5649 IO IC, functional same as 315-5338A, also used in Model 2/3, integrated into 315-6146 'MIE' MCU, etc
I/O overview: Connector (as described in service manual)
PORT-A 1st player inputs JAMMA (56P)
PORT-B 2nd player inputs JAMMA (56P)
PORT-C system input JAMMA (56P)
PORT-D system output JAMMA (56P) + CN25 (JST NH 5P) RESERVED OUTPUT 4bit. (?)
PORT-E I/O 1 CN32 (JST NH 9P) EXTENSION I/O 8bit.
PORT-F I/O 2 CN21 (JST NH 11P) EXTENSION I/O 8bit.
PORT-G I/O 3 CN20 (JST HN 10P) EXTENSION INPUT 8bit. (?)
PORT-AD AD-Stick inputs? CN19 (JST NH 12P) A/D INPUT 8Ch.
SERIAL COM CN18 (JST NH 6P) SERIAL COMMUNICATION
No idea if this is actually correct, but I guess Sound wouldn't work otherwise...
// ST-V seems to use PDR2O[4] to Reset the 68K?
//
// On Saturn, the SMPC has a specific Command and output pin for 68K Reset. ElectronAsh.
//
wire fx68k_extReset = (CART_MODE==3'd5) ? SMPC_PDR2O[4] : ~SNDRES_N;
Once I added that, the Sound Test in some menus did start to work / pass.
Clk Change test seems to fail, as it just goes to a black screen.
That could be a problem in games.
Oh yeah, this extra Factory Test menu, can be triggered by holding the TEST button as you start / reset the core...
Might even need to spoof the MIDI comms stuff, to get some games to run.
But that's probably just meant for a loopback cable, at the factory.
Sometimes, your battery just doesn't "enough".
Even the factory test menu sometimes crashes after a test, so that's not good. lol
There is so many different options for each game. Mahjong maybe the hard ones
Yeah.
And some weird connection schemes (and extra daughterboards) for others.
Ok, at least that seems to work.
I had to Reset the core though, since it crashed after the first test.
But the fact that it passes the Backup RAM test the second time, means that's working OK.
I'm sure that's just the same as how the Saturn uses the Backup RAM anyway.
Port D (outputs) test seems to work.
That just goes through each "bit" in the Factory menu.
Outputs from Port D seem to be active-High, for things like Coin Counters.
So they're unlikely to affect the games.
All of the port values can be read back by the SH4(s) atm, AFAIK.
Gonna spoof some ADC values in the core, but I very much doubt it will help boot games.
Also trying serial data loopback, just to see if I can get it to pass in the factory menu.
You never know, some of this stuff might help, but I'm just guessing.
Serial loopback test is half working.
But the Clock Change thing always crashes / black screens.
I could swear I had that test working before. Maybe on a different BIOS?
If that is failing, it could explain why certain games don't boot.
Since the Clock Change is basically for changing the pixel clock as well, for different video resolutions.
I would imagine many games need to use that.
For the most part, games like Die Hard seem to just outright crash, after the warning screen.
Where the SH2 jumps to some random code, or it just keeps trying to read until the end of mem space, then crashes fully.
The MAME code has a list of all the games that require a protection IC as well.
That could take a very long time to get added to the core. I don't think I could even do it.
Unless that part can be emulated on the ARM side.
Just tried Cotton Boomerang again.
But in Free Play mode (Test menu Coin settings).
Still won't react to Start 1 nor Start 2.
I don't think the game use a protection IC, as such, but I could be wrong.
And it only boots using the stv1061 BIOS so far, not the "correct" Japan epr-23603.ic8 BIOS.
So it might be just the game needs to detect the correct BIOS version.
The games own Test menu (EACH GAME TEST) won't even start with the 23602 BIOS. lol
Trying to start Cotton BM with the 23603 BIOS, it said "Checking the system", which usually means it's accessing the EEPROM.
(settings EEPROM)
But still goes to a black screen after.
So it "boots" the game fine with the stv1061 BIOS, but you still can't hit Start, basically.
It been a minute but I don’t think my STV has a special bios (I can take a look later) but I have one of those like 8 in 1 carts with games selectable by DIP and it can load like cotton, shienryu, guardian force, radiant silvergun and others I forgot. Not sure what tricks it may be using
No idea where or how or if ST-V reads the Area code.
I think on ST-V, that's purely based on which BIOS you use.
But I could be wrong.
I saw something about the region, in the MAME source.
Possibly some stuff is read via the old "joyports", which I need to look into.
A friend just found this...
I don't know how people even debug stuff like that. lol
It's for the Yabuse emulator, so I'll try to figure out how to modify the Saturn verilog.
I think this is the same/similar code in the core...
RW_N_OLD <= RW_N;
if (!RW_N && RW_N_OLD && !CS_N) begin
case ({A,1'b1})
7'h01: begin
{CONT,BREAK} <= DI[7:6];
IREG[0] <= DI;
end
7'h03: IREG[1] <= DI;
Line 1089, SMPC module.
git commit said "Continue is done only when IREG CONTINUE is 1. See Table 3.2 of SMPC doc"
OK, so it's writing to continue and break bits here...
7'h01: begin
{CONT,BREAK} <= DI[7:6];
IREG[0] <= DI;
end
(in the core)
emu patches...
// smpc.c, line 883...
if ((SmpcInternalVars->firstPeri != 0) && (SmpcInternalVars->timing <= 0))
{
//if (SmpcRegs->IREG[0] & 0x40) {
if ((SmpcRegs->IREG[0] & 0xC0) == 0x40) {
// smpc.c, line 894...
//else if (SmpcRegs->IREG[0] & 0x80) {
else if ((SmpcRegs->IREG[0] & 0xC0) == 0x80) {
Kronos is a Sega Saturn emulator. Contribute to FCare/Kronos development by creating an account on GitHub.
if ((SmpcInternalVars->firstPeri != 0) && (SmpcInternalVars->timing <= 0))
Ok, so that makes no sense to me. lol...
(SmpcRegs->IREG[0] & 0xC0) == 0x40
Because it's masking IREG[0] with 0xC0 first.
Which masks the upper two bits, [7:6].
But then checking if it equals 0x40.
Oh yeah, nevermind.
That's just checking if bit 6 is High.
switch(addr) {
case 0x01: // Maybe an INTBACK continue/break request
if (SmpcRegs->SF ==0) SMPCLOG("Request a continue/break but no intback on going\n");
if ((SmpcInternalVars->firstPeri != 0) && (SmpcInternalVars->timing <= 0))
{
if ((SmpcRegs->IREG[0] & 0xC0) == 0x40) { // Check if bit [6] (BREAK) is High.
// Break
SMPCLOG("INTBACK Break\n");
SmpcInternalVars->firstPeri = 0;
SmpcRegs->SR &= 0x0F;
SmpcRegs->SF = 0;
break;
}
// else if ((SmpcRegs->IREG[0] & 0x80)^(oldVal& 0x80)) {
else if ((SmpcRegs->IREG[0] & 0xC0) == 0x80) { // Check if bit [7] (CONTINUE) is High.
// Continue
SMPCLOG("INTBACK Continue\n");
SmpcSetTiming();
SmpcRegs->SF = 1;
}
}
return;
The core directly grabs those bits anyway, then has other logic to handle Break/Continue elsewhere.
case (COMM_ST)
CS_IDLE: begin
if (INTBACK_EXEC && (INTBACK_BREAK_PEND || VBLANK_PEND)) begin
INTBACK_BREAK_PEND <= 0;
WAIT_CNT <= 16'd70;
NEXT_COMM_ST <= CS_INTBACK_BREAK;
COMM_ST <= CS_WAIT;
end
// ......
// .....
if (CHECK_CONTINUE) begin
if (BREAK) begin
INTBACK_BREAK_PEND <= 1;
BREAK <= 0;
CHECK_CONTINUE <= 0;
end
else if (CONT != CONT_PREV) begin
INTBACK_PERI <= 1;
SF <= 1;
CONT_PREV <= CONT;
CHECK_CONTINUE <= 0;
end
end
OK, so INTBACK is actually a command.
(SMPC command, which the SH2(s) can send to it)
The SMPC is pretty much the Housekeeping chip on Saturn / ST-V.
Oh, hang on...
if ((SmpcRegs->IREG[0] & 0xC0) == 0x40) { // Check if bit [6] (BREAK) is High.
else if ((SmpcRegs->IREG[0] & 0xC0) == 0x80) { // Check if bit [7] (CONTINUE) is High.
I think I see why it masks BOTH bits now.
It would only trigger each of those IF statements, if only ONE bit is set at a time.
If BOTH bits were set, the compare would be 0xC0.
Gonna try this...
{CONT,BREAK} <= (DI[7:6]==2'b11) ? 2'b00 : DI[7:6];
ie. IF (both bits are High), then oh...
Maybe it should just block the write completely, rather than clearing both CONT and BREAK to zero.
if (DI[7:6]==2'b10 || DI[7:6]==2'b01) {CONT,BREAK} <= DI[7:6];
Only allows the write, if only ONE of the incoming bits is set.
No idea what I'm doing, but it's worth a shot.
By the way, if you find any errors with srg320's code, let him know.
Yep, will do.
It will all be on my fork of the core. So if I find any issues, I'll do a PR for it.
Looks like that's what the C code is effectively doing.
ie. ignorring the write, if BOTH bits are set at the same time.
So I'm running a compile now. You never know. lol
Takes about 25 mins to compile Saturn / ST-V, on my lowly 3700X.
I have the 5900X in the other room. I should probably swap them around.
Quartus said it was running out of mem earlier, whilst trying to compile the DC PVR thing.
This PC has 16GB.
The 5900X has 32GB.
🤞
oic...
Both bits set = No dinner for you.
So might be worth doing anyway.
I'm just not 100% sure if it's supposed to completely block the Write to the bits.
But we'll see.
In the core...
8'h10: begin //INTBACK
if (IREG[2] == 8'hF0 && (IREG[0][0] || IREG[1][3])) begin
if (IREG[0][0]) begin
WAIT_CNT <= 16'd800;
NEXT_COMM_ST <= CS_EXEC;
COMM_ST <= CS_WAIT;
end else begin
INTBACK_EXEC <= 1;
INTBACK_PERI <= 1;
INTBACK_OPTIM_EN <= ~IREG[1][1];
CONT_PREV <= 0;
COMM_ST <= CS_IDLE;
end
end else begin
COMM_ST <= CS_END;
end
end
IREG[0] is the register which gets written to for the Continue/Break thing.
But that's checking IREG[0] bit [0] there.
Probably Interrupt request masks.
Oh, OK.
The IREGs are generic registers, which can be used to write Parameters for each Command.
When IREG[0] bit [0] is set, the INTBACK command will grab a chunk of data for the Time, Cart code?, area code (Ludacris), terminal (serial??) status, SMEM?, Reset button status.
Results in the SR (Status Reg), and OREGs (output regs).
Not sure if ST-V checks the region code on the SMPC.
OK, now the Continue and Break stuff make sense.
For larger INTBACK requests, the data can't all fit into the handful of OREGs available.
So it generates an interrupt to let the SH2 know.
Then the SH2 can decide whether to grab the current data, then tell the SMPC to Continue grabbing the next chunk.
Or, BREAK, to stop the INTBACK command/request, and ignore the rest of the data
I would guess Cotton is using INTBACK to grab some info.
But AFAIK, ST-V doesn't use the SMPC Joyport stuff for most of the controls.
(it uses the separate IO chip, which is what I started adding.)
Obv makes no sense for code to set both the Continue and Break bits at the same time, so those writes should probably be blocked?
Still compiling. 21 minutes in.
Owww...
if ((SmpcRegs->IREG[0] & 0xC0) == 0x40) { // BREAK.
else if ((SmpcRegs->IREG[0] & 0xC0) == 0x80) { // CONTINUE.
That's an else-if.
Which means a BREAK always overrides a CONTINUE anyway.
I might need to tweak that.
That looks better.
if (DI[6]) BREAK <= 1'b1;
else if (DI[7]) CONT <= 1'b1;
Some games probably are just setting BREAK, with CONTINUE already set, so both bits.
With the old core code, it might have been locking up that stuff.
Coin-Ups likely work more often in games, as they are handled by the BIOS, AFAIK.
(most arcade machines need to always respond to Coin-Ups, even at initial power-up.)
Pretty much the only logic that handles those bits...
if (CHECK_CONTINUE) begin
if (BREAK) begin
INTBACK_BREAK_PEND <= 1;
BREAK <= 0;
CHECK_CONTINUE <= 0;
end
else if (CONT != CONT_PREV) begin
INTBACK_PERI <= 1;
SF <= 1;
CONT_PREV <= CONT;
CHECK_CONTINUE <= 0;
end
end
Where BREAK also overrides CONTINUE.
But... a BREAK doesn't seem to clear the CONT bit here?
The core took 31 minutes to compile.
The Service button now seems to work in the Cottom BM test menu.
So it can now move the cursor around the menu.
But... the Test button doesn't seem to work. lol
And now I haven't been able to get into the game at all. Just a black screen.
Even with the stv1016 BIOS.
Gonna take ages to debug all of this.
oic, that code above, checks for the rising "edge" of the CONTinue bit.
You would think a BREAK signal would always clear the CONT bit anyway?
Don't know.
if (DI[6]) BREAK <= 1'b1;
else /*if (DI[7])*/ CONT <= DI[7];
It needs to allow the SH2 to clear the CONT bit.
BREAK gets cleared right after it gets set, by the other logic above.
A CONT only gets triggered on the rising edge of the flag, but still has to get cleared by the SH2, then set again, to trigger another.
if (OREG_CNT == 5'd31) begin
SR[7:6] <= 2'b01;
SR[5] <= 0;
SR[3:0] <= 4'b1111;
if (IREG[1][3]) begin
INTBACK_EXEC <= 1;
INTBACK_OPTIM_EN <= ~IREG[1][1];
SR[5] <= 1;
CHECK_CONTINUE <= 1;
end
CONT_PREV <= 0;
MIRQ_N <= 0;
COMM_ST <= CS_END;
end
CHECK_CONTINUE gets set, if the OREG counter reaches 31, and if IREG[1] bit [3] is set.
OREG counter is going to be the thing that increments as the SMPC is grabbing the various chunks of data.
case (OREG_CNT)
5'd0: OREG_RAM_D <= {STE,RESD,6'b000000};
5'd1: OREG_RAM_D <= YEAR[15:8];
5'd2: OREG_RAM_D <= YEAR[7:0];
5'd3: OREG_RAM_D <= {DAY,MONTH};
5'd4: OREG_RAM_D <= DAYS;
5'd5: OREG_RAM_D <= HOUR;
5'd6: OREG_RAM_D <= MIN;
5'd7: OREG_RAM_D <= SEC;
5'd8: OREG_RAM_D <= 8'h00;
5'd9: OREG_RAM_D <= {4'b0000,AC};
5'd10: OREG_RAM_D <= {1'b0,DOTSEL,2'b11,~MSHNMI_N,1'b1,~SYSRES_N,~SNDRES_N};
5'd11: OREG_RAM_D <= {1'b0,~CDRES_N,6'b000000};
5'd12: OREG_RAM_D <= SMEM_Q;
5'd13: OREG_RAM_D <= SMEM_Q;
5'd14: OREG_RAM_D <= SMEM_Q;
5'd15: OREG_RAM_D <= SMEM_Q;
5'd31: OREG_RAM_D <= COMREG;
default:OREG_RAM_D <= 8'h00;
endcase
Anyway, Cotton 2 and Boomerang are now broken. lol
Haha blame me. I gave you additional ideas in DM
Clock Change stuff...
8'h0E: begin //CKCHG352
if (IRQV_N && !IRQV_N_OLD) begin
SSHRES_N <= 0;
SSHNMI_N <= 0;
SNDRES_N <= 0;
SYSRES_N <= 0;
DOTSEL <= 1;
COMM_ST <= CS_RESET;
end
end
8'h0F: begin //CKCHG320
if (IRQV_N && !IRQV_N_OLD) begin
SSHRES_N <= 0;
SSHNMI_N <= 0;
SNDRES_N <= 0;
SYSRES_N <= 0;
DOTSEL <= 0;
COMM_ST <= CS_RESET;
end
end
That is the test that fails, in the Factory test menu.
All it seems to do in the core, is flip the DOTSEL (pixel clock freq select) bit.
IRQV_N is likely waiting until the Vertical blanking interrupt, before flipping the DOTSEL bit.
Compiling with the other tweak, and some extra stuff added to SnargleFlap.
I won't post another RBF, until it's at a point where it's playing more games.
Or at least, at the same point it was before, with maybe a few more games allowing Start to be pressed.
Mah poor memory.
OK, so this code lets the game run, but Start still doesn't work...
if (DI[6]) BREAK <= 1'b1;
else /*if (DI[7])*/ CONT <= DI[7];
So no different to before.
But now I have some extra stuff in SignalFap to check.
This is the code that seemed to let the Service button work, in the game's Test menu...
if (DI[7:6]==2'b10 || DI[7:6]==2'b01) {CONT,BREAK} <= DI[7:6]; // Only allow write, if only one bit is set.
But it seemed to stop the game (Cotton BM) booting at all, even on stv1061.
Seems like it's quite common for both bits to be set by the CPU.
Since the BREAK bit will override how the logic responds to to the Continue thing.
But Continue only gets triggered on the Rising edge of CONT.
Which is what the PDF means by "reversing" the bit. ie. Clearing then Setting the bit again.
So I don't think the code is in the right place. It needs to just allow both bits to get written, from DI (Data In, from the SH2s), to the CONT and BREAK bits.
Then the other code needs to be tweaked, for when it's actually running the INTBACK command, and checking the CONT and BREAK bits there.
But it is weird how the Test menu service button started working, when I ignorred both bits being set / written
OK, so.
The CHECK_CONTINUE flag only gets set once OREG_CNT reache 31, AND if IREG[1][3] is set.
Then this chunk of code gets evaluated, in the CS_IDLE state...
if (CHECK_CONTINUE) begin
if (BREAK) begin
INTBACK_BREAK_PEND <= 1;
BREAK <= 0;
CHECK_CONTINUE <= 0;
end
else if (CONT != CONT_PREV) begin
INTBACK_PERI <= 1;
SF <= 1;
CONT_PREV <= CONT;
CHECK_CONTINUE <= 0;
end
end
Where the BREAK bit overrides the check for the rising edge of CONT.
hmm
I guess that makes sense, sort of.
If the BREAK bit is set, it sets INTBACK_BREAK_PEND, so it can cancel the INTBACK request elsewhere.
And it clears the BREAK bit at the same time.
If BREAK is clear when it does the check, it checks for the Rising edge of CONT.
Right now, in the Cotton BM title screen, the CONT bit is High...
Aaaand, the game crashed, as soon as I hit Coin or Start. lol
Cotton 2, first rising edge of CONT...
After that point, I never see another rising edge when hitting Start.
I feel like CONT needs to be cleared, when a BREAK happens.
See, the game is continually setting the BREAK bit...
Same thing in the game's Test menu, but I can't move the cursor. No reaction to Service nor Test.
Could try this...
if (CHECK_CONTINUE) begin
if (BREAK) begin
INTBACK_BREAK_PEND <= 1;
BREAK <= 0;
CONT <= 1'b0; // TESTING.
CHECK_CONTINUE <= 0;
end
else if (CONT != CONT_PREV) begin
INTBACK_PERI <= 1;
SF <= 1;
CONT_PREV <= CONT;
CHECK_CONTINUE <= 0;
end
end
Clearing CONT when it sees BREAK is set.
'cos you wouldn't expect a game to be able to set CONT at the same time anyway.
It should write BREAK, then it can set CONT again for the next INTBACK request.
Else, it will never see a rising edge of CONT, if the BREAK flag is High when it does CHECK_CONTINUE.
So, it does CHECK_CONTINUE when OREG_CNT reaches 31.
If BREAK is set, it triggers INTBACK_BREAK_PEND, and clears the BREAK bit.
If BREAK is NOT set at this point, it checks for a rising edge of CONT.
But, if both bits are already set, it will surely block it from seeing the rising edge of CONT?
Say if a game is setting both bits at once. ie. leaving BREAK set, when it sets CONT, it might never see the CONT rising edge.
Screw it. Another compile can't hurt.
Unless you hold your hand on the cpu heatsink
lol
Makes no sense to me, that the CONT bit would be left high, when a BREAK happens.
It's meant to just stop/cancel the request for more chonks of data.
It does make sense for it to only check those bits at the end of the first chonk, though.
Since it will always grab at least the first chonk, even if you set the BREAK bit before it has grabbed everything.
I reckon some games only ever write a 1 to the CONT bit.
ie. they don't toggle it, but clearing to 0, then setting to 1 again.
They expect the SMPC to react to the write of 1, every time (unless BREAK is set at the same time).
This part looks mostly OK...
else if (CONT != CONT_PREV) begin
INTBACK_PERI <= 1;
SF <= 1;
CONT_PREV <= CONT;
CHECK_CONTINUE <= 0;
end
But if BREAK doesn't clear CONT, and games only ever do CONT=1, then yeah.
Wait so do you have a British accent ash?
Yep, everything is in Colour, and I have an electric kettle.
Nice I’ve been reading your words wrong all this time
Please excuse me, whilst I ride my Penny-farthing into town...
No carbon tax for me.
Don’t worry you now sound like Hugh Grant in my head with less charming stammering
I'm definitely not THAT posh.
I was born in Essex. lol
I live in a weird corner of the UK with a very distinctive accent. (I'm not Australian!!!).
But also not as bad as that. ^
Nice one of the realtors on house hunters international may have the Essex accent. Sounds a lot like that
I think I might have seen that.
I genuinely think the CONT bit needs to be cleared when a BREAK happens.
Going by the SignalFlap screenshots above.
Like the game expects a Continue to be triggered, whenever it writes a 1.
And doesn't expect to have to clear CONT to 0, then set to 1 again, to re-trigger.
Well, sort of.
It probably does. lol
But it expects a BREAK to always clear CONT for it.
Games like Cotton maybe just use BREAK all the time, as they only need a smaller chunk of info.
Mah brain.
The IREG (or one of them) is used for some params that the actual INTBACK command uses.
The SMPC generates an interrupt, after grabbing the first chunk of data.
Then you can either write to the CONTinue or BREAK bit.
Would expect a BREAK to clear CONT for you.
Version with BREAK...
MAME...
If the SH2 writes to that with BREAK set, it ignores the CONT bit.
But it writes the data to IREG[0] regardless.
Also only allows writes to odd-numbered addresses, which the core already does.
Oww. It's still stuck.
I reckon, CONT should get cleared during the write itself, if BREAK is high.
Cotton 2 test menu still won't move.
{CONT,BREAK} <= (DI[6]) ? 2'b01 : {DI[7],1'b0};
If BREAK is set (from Data In), then force CONT Low, and BREAK High.
Else, allow the write from DI[7] for CONT, with BREAK set Low.
Determined to get something working tonight.
IREG[0] register still gets written, with the full byte...
IREG[0] <= DI;
(since it is used for parameter stuff fo commands. They just happen to shove the CONT and BREAK bits into the same reg write.)
From when I was clearing the CONT bit if BREAK is set, at the end of the first chonk...
Which is probably wrong.
There is an intentional delay before it "runs" each command.
Because the original SMPC chip is based on a small Hitachi 4-bit MCU.
But the core version is written as a Verilog state machine, so Srg320 added the delays to match.
Fuh
Tricky when that happens, as you have to change something in Quartus to get it to compile.
I just removed a few things from SnargleFlap, then closed Quartus, deleted the db and incremental_db folders, then restarted it.
Really very very annoying, but what can you do.
Still compiling.
23 minutes in.
Nope.
No change.
Same as it was yesterday.
Cotton 2 and BM run OK with the stv1061 core.
But don't react to Start.
And the Test menu won't move at all, again.
Very strange.
Clearing CONT, when BREAK goes high.
The only thing that helped slightly, was the old code...
if (DI[7:6]==2'b10 || DI[7:6]==2'b01) {CONT,BREAK} <= DI[7:6]; // Only allow write, if only one bit is set.
Which got the cursor moving in the game Test menu, but then couldn't start Cotton 2 nor Cotton BM at all.
Which strongly suggests the games very often leave the CONT bit high, when writing to the BREAK bit.
Cotton 2 test menu, triggers a BREAK, but then polls the IO chip Port regs right after?
Oh, for wasafari...
PORT_MODIFY("PORTG")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Winch")
Pretty much needs ALL of the ports added to the MiSTer joystick mapping thing.
Python script, to merge the upper and lower bytes of ROMs, for some games.
/* acclaim game, not a standard cart ... */
ROM_START( batmanfr )
STV_BIOS
ROM_REGION32_BE( 0x3000000, "cart", ROMREGION_ERASE00 ) /* SH2 code */
/* Thanks to Runik to point this out*/
ROM_LOAD16_BYTE( "350-mpa1.u19", 0x0000000, 0x0100000,)
ROM_RELOAD( 0x0200000, 0x0100000 )
ROM_LOAD16_BYTE( "350-mpa1.u16", 0x0000001, 0x0100000,)
ROM_RELOAD( 0x0200001, 0x0100000 )
ROM_LOAD16_WORD_SWAP( "gfx0.u1", 0x0400000, 0x0400000,)
ROM_LOAD16_WORD_SWAP( "gfx1.u3", 0x0800000, 0x0400000,)
ROM_LOAD16_WORD_SWAP( "gfx2.u5", 0x0c00000, 0x0400000,)
ROM_LOAD16_WORD_SWAP( "gfx3.u8", 0x1000000, 0x0400000,)
ROM_LOAD16_WORD_SWAP( "gfx4.u12", 0x1400000, 0x0400000,)
ROM_LOAD16_WORD_SWAP( "gfx5.u15", 0x1800000, 0x0400000,)
ROM_LOAD16_WORD_SWAP( "gfx6.u18", 0x1c00000, 0x0400000,)
ROM_REGION( 0x1000000, "rax", 0 )
ROM_LOAD( "350snda1.u52", 0x000000, 0x080000,)
ROM_LOAD( "snd0.u48", 0x400000, 0x200000,)
ROM_LOAD( "snd1.u49", 0x600000, 0x200000,)
ROM_LOAD( "snd2.u50", 0x800000, 0x200000,)
ROM_LOAD( "snd3.u51", 0xa00000, 0x200000,)
ROM_END
Trying Batman Forever, but it has the extra ADSP sound chip, so likely to get stuck.
Or should I say... Freeze.
Yeah, I know. Different movie. lol
I watched both of them at the cinema.
It was... a thing of its time.
chmod -x unify_roms.py
./unify_roms.py 350-mpa1.u19 350-mpa1.u16 350-merged.bin
If the two input ROMs are in the correct order, you should see the cart name in cleartext.
Then byteswapping of the rest, and merging...
dd if=gfx0.u1 of=u1 conv=swab
dd if=gfx1.u3 of=u3 conv=swab
dd if=gfx2.u5 of=u5 conv=swab
dd if=gfx3.u8 of=u8 conv=swab
dd if=gfx4.u12 of=u12 conv=swab
dd if=gfx5.u15 of=u15 conv=swab
dd if=gfx6.u18 of=u18 conv=swab
cat 350-merged.bin u1 u3 u5 u8 u12 u15 u18 > batmanfr_stv.bin
The game supposedly uses the Japan epr-23603.ic8 BIOS (in MAME).
It's possible it might boot, if it doesn't expect a reply from the sound board, and only sends commands to it.
No surprise. It doesn't boot.
Black screen.
Trying the stv1061 BIOS, but it's a long-shot.
Even without the sound ROMs, it ends up as a 32MB cart.
Something in the core definitely not getting Reset correctly, after it crashes.
Like the Program Counter for the SH2(s) wraps, then it just gets stuck?
I have to sometimes reload the RBF (or SOF).
Shows the ST-V spinning logo, lets you coin-up, but that's just the BIOS part.
Black screen after that. Oh well.
And it REALLY crashes. lol
Flatlines SignalFlap.
Contribute to sebdel/mra-tools-c development by creating an account on GitHub.
That might kinda work, if we had all of the MRAs for ST-V already.
Test menu for dnmtdeka works.
But the game crashes, ofc.
It's essentially Die Hard, Japan edition, AFAIK.
We may need a dedicated channel for STV 😊
So it didn't quite hit 50 MHz.
Only 25 MHz for now.
At 50 MHz, it was getting stuck whilst rendering.
And jumping to some random isp_state, which should obviously never happen.
This is all working from DDR3 now. The SDRAM isn't being used at all.
When the VRAM dump file first loads, you can see it display the Framebuffers that reicast already pre-rendered into the file.
But you're seeing both Framebuffers, just on odd and even pixels.
As soon as the file has done loading, the Verilog renderer kicks in, and crappofies the image.
But this is a good demonstration of why DDR (generally) sucks for latency...
Even with the core running at 25 MHz, and the DDR3 running at (I think) 400 MHz.
It's taking around 6 (core) clock cycles, just to read ONE 64-bit word from DDR3.
If it only took three clock cycles, it would literally render three times faster.
DDR is only really good when taking advantage of burst transfers.
And to a similar extent, standard (SDR) SDRAM.
Luckily, one benefit of the tile rendering, is that there should be just enough on-chip mem on the FPGA for the parameter cache, texture cache, Codebook cache, tile ARGB buffer, etc.
That should speed it up a LOT.
Even just having the ARGB buffer would help, because you can render pixels directly to that, with zero wait state.
Then burst write the whole tile (1,024 pixels) into DDR.
The real PVR probably pre-reads some texture data into cache, too.
Once it's in cache, it likely has very low latency as well.
It's taking roughly 1.5 seconds to render one frame atm, at 25 MHz.
If the DDR latency was only three clock cycles, it would render at around 4 FPS.
And this is kind of doing a "direct" render atm. Rather than generating the Tags first.
So it's doing tons of overdraw, essentially.
It's daunting, thinking about getting some of that stuff onto the FPGA. lol
Just because of the ~24 minutes it takes for a Quartus compile, and there are always problems.
The good news is, the sim renders are much closer than I thought to the reicast renders.
reicast...
Sim (verilog)...
The missing Sky texture is due to Z precision.
And no Punchthrough for the decals atm, until the ARGB tile buffer is added.
But even without texture filtering, I think it looks pretty good now.
Latency is SO bad. lol
That's how long it takes, just to read one texel, and write one pixel.
And that's with the core at 25 MHz, so each clock tick on SignalTap is 40ns.
What kind of romset do you use? The core specifies .bin but that’s not the common file type for ST-V. Also, that’s a system I know well so I can help to identify strange behaviors and make intensive testing.
Hi.
I don't know the exact version of the ROMs.
I'm currently using MAME 0272b, though.
The ROMs were just whichever MAME zips I found.
The .bin is not standard, no. It's just a single-file merge of all of the separate ROMs.
But it often needs to be padded out, by doing things like duplicating the first ROM file, so the rest of the ROMs end up at the correct offset within the BIN.
The other reason I have to add the .bin extension, is to prevent the MiSTer OSD from hiding the files.
Usually, the MiSTer OSD file browser will only show the files which have extensions matching what is in the CONF_STR.
(and string within the core itself)
"FS3,BIN,Load cartridge;",
But yep, the bin file is just a "raw" binary of all of the ROMs for the game.
Some ROMs need to be byteswapped as well, before merging / concatenating.
An example here. Not that the specific game actually runs yet. lol...
#1315008851874938948 message
Eventually, if enough of the issues can get fixed, and far more ST-V games run, it will probably get proper MRA file support.
AFAIK, MRA files get generated from the MAME code, using scripts?
MRAs are just XML files which tell the main MiSTer process how to load the ROMs (byteswapping etc.), and which address offsets to load them into.
On the Saturn core, almost all memory uses DDR3, including main SH2 mem, the VDP VRAMs, and Cart "ROM".
atm, when loading an ST-V game as a "cart", MiSTer expects the data in one contiguous file.
I'm confident the ROM data is getting loaded into DDR3 OK.
But definitely not so sure about the crusty logic I added to the Saturn core.
When the MiSTer menu option Cartridge Type is set to ST-V now, it basically just gives it the whole 25-bit address to use.
(minus the LSB bit)...
wire [24:1] STV_ADDR = AA[24:1];
That small snippet of code was actually already present in the Saturn core.
I just added the extra menu choice for it.
Most of the rest of the tweaks I had to do in the ddram.sv module...
if ({ACS0_N,cart_addr[24:4]} != cart_rcache_addr[25:4] || cart_rcache_dirty) begin // Check if the READ addr has changed. Or if dirty, due to a previous WRITE.
But using the ASC0_N signal as if it were bit 25 of the Cart address.
I couldn't use bit 25 directly from the SCU, because that bit is usually High, for the whole lower 32MB of ABUS space...
There wasn't too much other stuff I added to allow for loading of larger carts, tbh.
Only other thing was adding Jotego's implementation of the 93C46 EEPROM, as many games refused to boot at all without that.
Then I wrote a rough version of the IO chip, for the controls...
Oh, and tweaked this, in the main saturn.sv (there are two files with that same name).
//wire [25:1] IO_ADDR = cart_download ? {4'b0011,ioctl_addr[21:1]} : {7'b0000000,ioctl_addr[18:1]};
wire [25:1] IO_ADDR = cart_download ? ioctl_addr[25:1] : {7'b0000000,ioctl_addr[18:1]};
That allowed loading of larger Cart BINs, up to 64MB, which would fill the whole ABUS CS0 and CS1 mem spaces, I think?
This probably isn't a great idea...
wire STV_IO_CS = (MSHA[24:0]>=25'h400000 && MSHA[24:0]<=25'h40003f);
assign MSHDI = STV_IO_CS ? STV_IO_DOUT : CDO;
ie. only checking the lower 25 bits of the address from the Master SH2.
It could well be clashing with other stuff.
It should be made more robust than that.
@rain obsidian Hi, may I ask You a little info to understand how to make Shienryu working? I bytesewpped the 3 parts of the ROM then I concatenated the files in one file, but no luck. Do I have to duplicate the first part? If yes, how many times?
There Is also a file eeprom-shienryu.bin.... Do I have to concatenate also this?
Thanks ElectonAsh, you are making a great work!!!!
Thanks.
There is no EEPROM saving / loading support yet.
So it kind of just stays blank when you start the core, and the games can read/write the defaults to it.
It's just there to hopefully allow more games to at least try to start up.
ROM_START( shienryu )
STV_BIOS
ROM_REGION32_BE( 0x3000000, "cart", ROMREGION_ERASE00 ) /* SH2 code */
ROM_LOAD16_WORD_SWAP( "mpr19631.7", 0x0200000, 0x0200000,
ROM_LOAD16_WORD_SWAP( "mpr19632.2", 0x0400000, 0x0400000,
ROM_LOAD16_WORD_SWAP( "mpr19633.3", 0x0800000, 0x0400000,
ROM_REGION16_BE( 0x80, "eeprom", 0 )
ROM_LOAD( "eeprom-shienryu.bin", 0x0000, 0x0080, CRC(98db6925) SHA1(e78545e8f62d19f8e00197c62ff0e56f6c85e355) )
ROM_END
Thanks ElectornAsh. So no need to put the EEPROM file. Anyway the first file (mpr19631.7) must be duplucated twice, correct?
dd mpr19631.7 of=rom7 conv=swab
dd mpr19632.2 of=rom2 conv=swab
dd mpr19633.3 of=rom3 conv=swab
cat rom7 rom7 rom2 rom3 > shienryu_stv.bin
I think that's right for that game, but I can't remember now. lol
Ignorring the EEPROM file for now, as it can't load that (yet).
The mpr19631.7 is the actual SH2 code for the game.
But that file is only 2MB.
So it has to be repeated twice, to pad the "gap" between mpr19631.7 and mpr19632.2.
The other two ROMs are 4MB each, so they should be OK as-is.
But you do need to Byteswap all three ROMs first, in this case.
This is actually easier to do in WSL now, if you're on Windows.
ie. vs messing with finding a tool to do it in a DOS prompt.
Check your DMs though, @static mountain 😉
Be aware that even if you get a game running, it is prone to crashing atm. Not sure how to fix that yet.
Shienryu seemed to crash for me after dying, and when it seemed to be reading data from the ROM again.
I'm sure all of this will get fixed eventually, but I don't know how much time I'll have to spend on it.
It's also super time-consuming, as I can only really test it by doing multiple Quartus compiles.
And those take 25-30 minutes each time.
It needs one of the uber devs like Srg320 (the Saturn core's author) to look into it really.
Trying that last tweak atm.
//wire STV_IO_CS = (MSHA[25:0]>=26'h0400000 && MSHA[25:0]<=26'h040003f);
wire STV_IO_CS = (MSHA[26:0]>=27'h0400000 && MSHA[26:0]<=27'h040003f);
Since it wasn't checking bit [26] of the SH2 address before, STV_IO_CS was likely triggering on other upper address ranges, too.
Which is really bad, as it would have been stomping all over the reads.
That would have included all of the 0x05000000 range stuff for VDP1. Oops.
CS0_N <= ~(A[26:25] == 2'b00);
CS1_N <= ~(A[26:25] == 2'b01);
CS2_N <= ~(A[26:25] == 2'b10);
CS3_N <= ~(A[26:25] == 2'b11);
From the Saturn core SH2, BSC.sv, line 542. ^
So I should really be using CS0_N for the IO chip stuff.
I really don't like the use of the bitwise NOT there. lol
I mean, OK, the stuff within the braces evaluates to a single bit boolean (True or False), but still.
@rain obsidian Ohhh thanks for helping me. You are so kind
np. 😉
I just can't promise if/when the ST-V stuff will improve.
It just kinda watched VGEs video on it, and thought I'd try patching the Saturn core.
If this next compile of the Saturn core improves anything at all, I'll post the RBF on here.
tbh, I'm not expecting it to improve anything, but we'll see.
If it’s not much burden report back @static mountain on how stable shienryu is, I might set up even this POC work just to be able to TapTo launch it on my vertical cab. 😉
Still working on DC.
I just saved a bit of logic in the inTri unit, by pre-calculating some values that use subtractions.
But those few modules (near the top-left) are still using a massive chunk of logic.
Like, 38,320 Logic Elements. lol
I tried to reduce them as much as I could, including asking Claude AI for various ways to optimize it.
Most FPGA renders aren't great atm.
I'm just happy to see it running all from DDR3 right now.
I do think DDR3 is more suited for VRAM, especially after seeing how much the Saturn (core) uses DDR for everything.
But it will need caches and burst transfers, to get the speed up.
(there's still a kind of double image as well, as I'm not quite sure how to modify ASCAL to display the Framebuffer correctly.)
I do have Z interpolation and Paletted textures enabled, though.
I like textureless or flat shaded or whatever is going on DOA pic, just leave it like that
Which would have NEVER fit the FPGA previously.
lol
I quite like it too, in some way.
When it's first loading the VRAM dump, it shows the reicast frames.
Which is very much cheating, but a super handy comparison.
Actually, it's showing BOTH frames, on alternate pixels.
Finally learning to use github more often.
Or, doing a git commit more often.
It frees up your brain, to not worry so much about making a big code change.
github shouldn't really be used as a "backup", but it kind of is. lol
No change with the ST-V thing.
All games that were broken before, are still broken.
Cotton 2 / BM still won't react to Start.
Nor Guardian Force.
When some games crash, they really do crash.
The SH2 seems to jump to a wrong location in Cart ROM.
Then it just blindly increments the SH2 address until it wraps, and freezes.
The Saturn core could do with a proper Reset controller, too.
Since Reset in the menu doesn't do a full Cold Reset.
I have to reload the core, which loads the Saturn BIOS (boot0.rom) by default.
Then try loading an ST-V BIOS again, like stv1061.bin.
(and if there is still a game in memory which crashes, I have to quickly load a different Cart ROM. lol)
Dynamite Deka does the same thing as Die Hard.
It dies... hard. That sounded wrong.
Die Hard does at least show the Winners Don't Do Drugs thing, before crashing.
Stop doing drugs and maybe it will get further
A project you might be interested in Ash, that came up in the N64 channel, what would it take to get the N64 core to load raw Aleck64 dumps? It can play patched ROMs, but can't seem to find info on what was actually patched. Maybe within your skillset, like you have been doing with S-TV, to do some digging and proof of concept work to see if core could potentially play the raw dumps.
@rain obsidian I'm still trying to find a working BIOS but looking at your screenshots, there's something weird compared to real ST-V hardware. You shouldn't have 4 cart slots enabled. The other slots are intended to be used with external hardware like Batman Forever. On regular basis, there's a dummy cart that should be in place in a slot in order to boot a cart properly.
Oh yeah that little null connector thing
its really not for use. Its for Ash to play with
I was just watching VGEs vid on cosam's "Nintendo Playstation" prototype PCB.
And somebody in the comments mentioning N64 DD.
Which made all kinds of ideas float around in my brain. lol
Not sure about Aleck64, but I don't think it was too much different from the stock N64.
Similar to the ST-V, I think they just added an extra IO chip.
I don't know if I'll ever get around to that, though. And there is one other BIG hurdle...
The N64 core was written in VHDL.
It makes it MUCH harder for me to figure out the code, it's just hard to "scan" things quickly.
Yep, the Multi-cart thing isn't implemented properly, since there is no bank switching register etc.
I haven't looked into that too much, as I was hoping it would just ignore that if the BIOS was set to "Alone" (single cart).
But it is very possible that the BIOS (or game) is trying to scan the extra slots, but just seeing a repeat of the existing Cart ROM, or reading extra garbage (uninitialized memory) from DDR3 above where the ROM is loaded.
Lots of questions about it, as I'm also learning more about the system as I go along.
I still don't even know exactly what all of the hardware differences are between Saturn and ST-V.
As just one example - I did a tweak to change how the 68K for the Sound chip gets reset.
The Saturn uses a specific output pin from the SMPC to reset the sound 68K.
On ST-V, it looks like it does it a different way (according to the MAME code), where it uses one of the "spare" joyport pins instead.
ie. the Joyport ports/pins still exist on the SMPC chip on the ST-V, but a handful of them are used for different things.
Since the ST-V has the extra IO chip (similar to the Mega Tech) to handle the JAMMA edge and most of the other connectors, it doesn't use those traditional Joyport pins in the same way as the Saturn.
Ideally, we'd have to go through all of the MAME code, and note down all of the differences between Saturn and ST-V.
Also, some games of course use a protection IC, to decrypt the cart ROM.
That IC can also be interrogated directly, to do other checks in the game.
It looks like it's basically the same IC used in many NAOMI carts.
But looks SUPER complex to try to implement in Verilog. lol
It might be best to find patched versions of those games, if such a thing even exists.
Or maybe even run the protection IC stuff from the main MiSTer app on the ARM side.
That is totally doable, but it's a lot of work to get running and debug.
Any write requests from the FPGA side would need to be (reliably) captured.
And any responses from the protection IC code very quickly returned from the ARM to the FPGA.
(games like Radiant Silvergun - won't react to the Start button at all, unless it can read the protection IC. That's a separate issue to other games like Cotton not reacting to Start, AFAIK.)
@frozen pawn I might have a look at the Multi-cart bank switching later, and try to implement it so it always thinks it's a single-cart system.
But I'm still working on Dreamcast as well, and all kinds of things. hehe
I can make more tests if you need but I just need a valid bios file. I tried everything and I still have a black screen and can’t boot any game
My videos are your rabbit holes 🤣
Really the idea should be “we could totally implement the SNES CD boot rom and send data in via imaginary FPGA code like a cd rom drive
I very nearly did my own version of the SuperDisc mobo.
But then it came down to the one main metric for a retro project...
How many (good) games can it run... NOW.
“Will it get me laid”
Unless you happen to find yourself in a dark alley, caught by two 7-ft men in Fursuits.
I’m curious what he’s planning on using for the cd silicon since that seems bespoke Sony
You've never known fear, until you're confronted by a 7ft Colley Dog, and an 8ft Fox.
Unless those chips are hiding in a portable cd player or some other obscure Sony part and nobody knows yet
Man, where do I even start with the CD drive stuff. You saw my tweets, right? lol
I found what I believe is almost the same drive mech as in the SuperDisc.
As far as I could see (both years ago, and the other day), the only "custom" parts are the small Gate Array which lets the SNES side talk to the CD chipset.
And the small MCU on the top LCD board, with the CD audio controls etc.
Would make sense Sony used as many off the shelf parts they had for the job
The rest of it is just standard Sony / Philips / Sanyo style CD-ROM crap, from that generation.
IIRC from the Tweets, the CD mech they used is found in some Sony hifis around that time.
Really it’s convenient SNES CD was nothing more than “alternate media” solutions
Didn’t add any “power” to the system
Quite hard to find the posts now. The search system on Xitter isn't great.
It's for sure possible for a CD drive addon to be made for the stock SNES, btw.
Assuming somebody did the work of figuring out the basics of the Gate Array.
tbh, I don't think it would be doing much.
But let's not get me into yet another distraction project. lol
Yeah, I've had to learn to try not to get distracted by new shiny projects.
Some of them were things I wanted to try years ago, though.
I still haven't given up on the idea of getting two N64s running in lock-step.
So I can have them do Stereo 3D, in hardware.
(modifying the projection matrix in the game code of one of the Cart ROMs, to shift the camera view slightly.)
But again, very novelty, not very useful / desirable.
At least this is looking a little bit cleaner.
Can't prevent the jaggies, until I can tweak ASCAL properly.
It's kind of unique to DC, that it organizes the VRAM the way it does.
Sega's way of showing the VRAM...
(or PowerVR's way)
I found it hard, thinking about the upper and lower 4MB stacked vertically, for some reason.
My version...
_________ _________
| | | |
| | | |
| 2nd 4MB | | 1st 4MB |
| | | |
| | | |
|_________| |_________|
[63:32] [31:0]
That's why ASCAL has trouble displaying the framebuffer correctly.
As it needs to read two (16-bit) pixels from the lower bits [31:0] first.
Then SKIP to the next address, read two pixels, etc.
I actually load the 8MB VRAM dump from reicast in that format.
The first 4MB gets written to the lower 32-bits of the 64-bit word, using the DDRAM Byteenables.
Then the upper 4MB.
That's the only logical way to do it, to allow it to read textures as 64-bit wide.
(without having to do TWO texture reads every time, from different addresses.)
I need to get ASCAL to shift the data down twice as quickly, and also increment the read address twice as quickly.
Don't think I have the brain power to spare, to work on ST-V much tonight, sorry.
Especially with this CRAP happening. sigh
What a piece of poo. lol
Just noticed this in the MAME code for ST-V...
/* fix endianess */
Which seems to Word-swap the cart ROMs during loading, but I'm not sure why.
Like, a 32-bit byteswap.
Even though the usual loading code already has options for 16-bit Byteswap...
ROM_START( shienryu )
STV_BIOS
ROM_REGION32_BE( 0x3000000, "cart", ROMREGION_ERASE00 ) /* SH2 code */
ROM_LOAD16_WORD_SWAP( "mpr19631.7", 0x0200000, 0x0200000,
ROM_LOAD16_WORD_SWAP( "mpr19632.2", 0x0400000, 0x0400000,
ROM_LOAD16_WORD_SWAP( "mpr19633.3", 0x0800000, 0x0400000,
ROM_REGION16_BE( 0x80, "eeprom", 0 )
ROM_LOAD( "eeprom-shienryu.bin", 0x0000, 0x0080,
ROM_END
If I had to do that endian swap for all ROMs, though, nothing would boot on the core.
So that's probably just the usual Intel little-endian thing.
(ie. MAME might need to do that extra step, but we don't.)
void stv_state::stv_select_game(int gameno)
{
if (m_prev_gamebank_select != gameno)
{
if (m_cart_reg[gameno] && m_cart_reg[gameno]->base())
memcpy(memregion("abus")->base(), m_cart_reg[gameno]->base(), 0x3000000);
else
memset(memregion("abus")->base(), 0x00, 0x3000000); // TODO: 1-filled?
m_prev_gamebank_select = gameno;
}
}
OK, so the SMPC is used to select the Bank / Cart slot?
Only triggers that stuff if the game number has changed since the last write.
lol. They actually do a memcpy for that.
Looks like MAME just stores each cart "slot" in a separate array. Fair enough.
Else, they seem to zero out the unused cart slot data.
So, they are using PDR1 to select the cart slot...
void stv_state::pdr1_output_w(uint8_t data)
{
m_eeprom->clk_write((data & 0x08) ? ASSERT_LINE : CLEAR_LINE);
m_eeprom->di_write((data >> 4) & 1);
m_eeprom->cs_write((data & 0x04) ? ASSERT_LINE : CLEAR_LINE);
stv_select_game(data & 3);
}
I'll see if I can just store that value, and force it to read back 0x00 for any slot other than slot 0.
wire [1:0] cart_slot = SMPC_PDR1O[1:0];
if (ABUS_WAIT && MEM_RDY) begin
case (MODE)
3'h0: ABUS_DO <= 16'hFFFF;
3'h5: ABUS_DO <= (cart_slot>0) ? 16'h0000 : MEM_DI; // ST-V. Force readback of 0x00 for cart_slot > 0.
default: ABUS_DO <= MEM_DI;
endcase
Port G counter / READ stuffs in MAME...
case 0x0d:
if (m_ioga_mode & 0x80) // PORT-G in counter mode
{
uint8_t const sel = (m_ioga_portg >> 1) & 0x03;
res = ((m_ioga_counters[sel]->read() - m_ioga_count[sel]) >> ((~m_ioga_portg & 1) * 8) & 0xff);
m_ioga_portg = (m_ioga_portg & 0xf8) | ((m_ioga_portg + 1) & 0x07); // counter# is auto-incremented on read
break;
}
Don't get if the counters auto-increment from a clock divider, or only on a read?
Port G write stuffs...
case 0x0d:
if(!BIT(data, 7)) // when bit 7==0 reset counters
{
for(unsigned i = 0; m_ioga_counters.size() > i; ++i)
m_ioga_count[i] = m_ioga_counters[i]->read();
}
m_ioga_portg = data;
break;
Ohhh, I see.
"counter# is auto-incremented on read"
Not very obvious. lol
Counter NUMBER is auto-incremented.
ie. Which counter is currently selected.
I really dislike C/C++ sometimes..
I never learned how to use classes, etc.
And things like the keyword "THIS".
// m_smpc_hle->sound_reset_handler().set(FUNC(saturn_state::sound_68k_reset_w)); // ST-V games controls reset line via PDR2
This is how I'm handling that in the core atm...
// ST-V seems to use PDR2O[4] to Reset the 68K?
//
// On Saturn, the SMPC has a specific Command and output pin for 68K Reset. ElectronAsh.
//
wire fx68k_extReset = (CART_MODE==3'd5) ? SMPC_PDR2O[4] : ~SNDRES_N;
But I'm not resetting the SCSP sound chip itself, so I need to fix that.
void stv_state::pdr2_output_w(uint8_t data)
{
m_audiocpu->set_input_line(INPUT_LINE_RESET, (data & 0x10) ? ASSERT_LINE : CLEAR_LINE);
m_en_68k = ((data & 0x10) >> 4) ^ 1;
SCSP should get reset when SMPC_PDR2O[4] is High.
Same for the 68K. So it's the same signal.
(just kind of inverted in MAME, because it has m_en_68k, which will be active-High.
wire fx68k_extReset = (CART_MODE==3'd5) ? SMPC_PDR2O[4] : ~SNDRES_N;
wire SCSP_STV_RST_N = (CART_MODE==3'd5) ? !SMPC_PDR2O[4] : RST_N;
case 0x06:
Last compile didn't work.
Not even the BIOS booted, so it must have been my code that forced a read of 0x0000 if cart_slot > 0 .
Can't rely on just that, unless the defaults for PDR1 are zero after Reset.
I don't get how the Port G counters work.
case 0x06:
if (m_mode & 0x80) // port G counter mode - 4x 16bit counters, auto-increments
{
data = m_cnt_cb[(m_port_value[6] >> 1) & 3](0) >> (((m_port_value[6] & 1) ^ 1) * 8);
if (!machine().side_effects_disabled())
m_port_value[6] = (m_port_value[6] & 0xf8) | ((m_port_value[6] + 1) & 7);
break;
}
Oh, cb = callback.
sega_315_5649_device::sega_315_5649_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, SEGA_315_5649, tag, owner, clock),
m_in_port_cb(*this, 0xff),
m_out_port_cb(*this),
m_an_port_cb(*this, 0xff),
m_serial_rd_cb(*this, 0),
m_serial_wr_cb(*this),
m_cnt_cb(*this, 0),
m_port_config(0),
m_mode(0),
m_analog_channel(0)
Don't get it. Maybe never will.
Tracing code through MAME got so much harder, once they started moving from pure C to more C++.
Trying to understand this first...
void stv_state::stv_ioga_w(offs_t offset, uint8_t data)
{
offset &= 0x0f; // mirror?
switch(offset * 2 + 1)
{
case 0x0d:
if(!BIT(data, 7)) // when bit 7==0 reset counters
{
for(unsigned i = 0; m_ioga_counters.size() > i; ++i)
m_ioga_count[i] = m_ioga_counters[i]->read();
}
m_ioga_portg = data;
break;
}
}
uint8_t stv_state::stv_ioga_r(offs_t offset)
{
uint8_t res;
offset &= 0x0f; // mirror?
switch((offset * 2) + 1)
{
case 0x0d:
if (m_ioga_mode & 0x80) // PORT-G in counter mode
{
uint8_t const sel = (m_ioga_portg >> 1) & 0x03;
res = ((m_ioga_counters[sel]->read() - m_ioga_count[sel]) >> ((~m_ioga_portg & 1) * 8) & 0xff);
m_ioga_portg = (m_ioga_portg & 0xf8) | ((m_ioga_portg + 1) & 0x07); // counter# is auto-incremented on read
break;
}
[[fallthrough]];
}
}
(other cases removed from the code above.)
m_ioga_portg is just a register that stores the data on a write.
Seems to be just the four counter regs.
required_ioport_array<4> m_ioga_counters;
This line, just increments the lower three bits on a read...
m_ioga_portg = (m_ioga_portg & 0xf8) | ((m_ioga_portg + 1) & 0x07);
(before storing the result to the Port G reg.)
This is the only part doing any actual "counting"...
(sel bits come from bits [2:1] of the Port G reg.)
res = ((m_ioga_counters[sel]->read() - m_ioga_count[sel]) >> ((~m_ioga_portg & 1) * 8) & 0xff);
What a mess. lol
OK, so bits [2:0] of Port G are used, but it's masking those first, two use bits [2:1] for sel.
Then using the LSB bit (inverted) of the Port G reg to mult an offset of 8, or something.
Oh yeah, probably shifting down the result of the counter update result, because you can only read an 8-bit value from any of the ports.
Nearly got it, I think...
On a WRITE...
if (PORTG_CS) begin
if (!MSHDO[7]) begin // Reset counters if Bit[7] of the write data is Low...
CNT_VAL[0] <= PORTG_CTR[0];
CNT_VAL[1] <= PORTG_CTR[1];
CNT_VAL[2] <= PORTG_CTR[2];
CNT_VAL[3] <= PORTG_CTR[3];
end
PORTG_OUT <= MSHDO[7:0]; // Still write the full byte to the Port G output reg.
end
On a READ...
// PORT G in Counter mode...
if (PORTG_CS && PORTG_MODE) PORTG_OUT[2:0] <= PORTG_OUT[2:0] + 1'd1; // Increment to the next Counter SELECT.
Then the actual calc, done with combo logic...
reg [15:0] CNT_VAL [0:3];
reg [15:0] PORTG_CTR [0:3];
wire [15:0] CTR_CALC = PORTG_CTR[ PORTG_OUT[2:1] ] - CNT_VAL[ PORTG_OUT[2:1] ];
wire [7:0] CTR_MUX = (PORTG_MODE) ? CTR_CALC>>((!PORTG_OUT[0])*8) : PORTG_OUT;
Bits [2:1] of the Port G register (PORTG_OUT) select the Counter and Count Value to do the subtract thingy.
Bit[0] is then used to shift the data right by 8 bits, so it can read the upper Byte of the counter calc result.
If PORTG_MODE is Low (not in counter mode), then it just allows readback of the PORTG_OUT reg.
(that needs to be fixed, too, so it can read Port G inputs, depending on the DIRection reg.
There's a separate MODE register you can write to on the IO chip...
// MODE reg notes. (from MAME).
//
// 7--- ---- port G counter mode
// -6-- ---- ?
// --5- ---- RS-422 satellite mode
// ---4 ---- RS-422 loopback
// ---- 3210 RS-422 satellite N#
reg [7:0] MODE_REG;
wire PORTG_MODE = MODE_REG[7];
wire RS422_SAT = MODE_REG[5];
wire RS422_LOOP = MODE_REG[4];
wire [4:0] RS422_NODE = MODE_REG[3:0];
If bit 7 is set, it puts Port G into Counter mode.
If you then WRITE to Port G (regardless of the mode?), it resets the four counters, and still stores the full byte to the Port G reg.
Nope, the m_ioga_count (CNT_VAL) must be incrementing or decrementing elsewhere in the MAME code.
I would expect them to run at a specific clock freq, but it's hard to find the code.
Looks like CNT_VAL is essentially the clock divider for each counter.
uint8_t m_ioga_mode = 0;
uint8_t m_ioga_portg = 0;
uint16_t m_ioga_count[4]{};
A bit neater...
// PORTG Counters, calc, and Read mux.
reg [15:0] CNT_DIV [0:3]; // Clock divider value, for each counter?
reg [15:0] COUNTER [0:3]; // The actual counter regs.
wire [15:0] CTR_CALC = COUNTER[ PORTG_OUT[2:1] ] - CNT_DIV[ PORTG_OUT[2:1] ]; // Using bits [2:1] of Port G, to select the Counter.
// Subtract CNT_DIV (divider) from the Counter Reg value.
// (don't actually WRITE to the Counter reg!?)
wire [7:0] CTR_READ = (!PORTG_OUT[0]) ? CTR_CALC[15:8] : CTR_CALC[7:0];
wire [7:0] CTR_MUX = (PORTG_MODE) ? CTR_READ : PORTG_OUT;
CTR_READ mux, is used to select the upper or lower Byte of CTR_CALC.
(could have been done as a shift in Verilog, but this makes more sense to my brain.)
Needs more tweakage.
'cos atm, it will be incrementing the counter select bits multiple times.
Until I add proper logic for the bus timings, to act only on rising or falling edges of some control signals.
(a read or write spans multiple clock cycles. The BS_N signal gets asserted during an SH2 bus cycle. MSHRD_WR_N denotes whether it's a Read or Write, etc.)
I guess this helps answer the question, about roughly how much logic PVR2 might take. lol
I'm sure a lot of that is due to how I structured the regs for the Z Buffer / Prim Tag buffer.
So it can't infer that as BRAMs, and instead is using tons of registers.
I'm not sure if I have all of the code from the sim hooked up yet.
I just needed to get it to finish the first compile, to give me an idea of what I'm working with.
reg [40:0] z_col [0:31] [0:31];
The Z-Buffer is a 2D array of registers that are 41-bits per entry.
Since I need to store a 32-bit Z value, and at least 9 bits for the prim_tag.
(it's actually 48-bit Z in the sim, but I was trying to save a bit of logic for the first Quartus compile.)
That's around 5.125 KBytes of memory, so not a huge amount.
But it needs to be written in a way that can be inferred as a standard RAM block.
ie. So you're not trying to access some random entry, while at the same time trying to write a value elsewhere.
You can only do so much with a Dual-Ported RAM instance, as it will usually just have the two address/data ports.
It also has a mux on the "input", to let me Clear the Z-buffer, before each tile is rendered.
Trying it with only half of the registers for the Z buffer.
It also has 32 instances of the depth_compare logic.
There really isn't another way to do it, AFAIK.
It has to do a per-pixel depth (Z) compare.
This is the entirety of the depth_compare module...
module depth_compare (
input [2:0] depth_comp,
input signed [47:0] old_z,
input signed [47:0] IP_Z,
output reg depth_allow
);
always @(*) begin
case (depth_comp)
0: depth_allow = 0; // Never.
1: depth_allow = (IP_Z < old_z); // Less.
2: depth_allow = (IP_Z == old_z); // Equal.
3: depth_allow = (IP_Z <= old_z); // Less or Equal
4: depth_allow = (IP_Z > old_z); // Greater.
5: depth_allow = (IP_Z != old_z); // Not Equal.
6: depth_allow = (IP_Z >= old_z); // Greater or Equal.
7: depth_allow = 1; // Always
endcase
end
endmodule
I'm gonna try forcing it to Greater-than in the sim, and see what the renders look like.
Apparently looks fine.
So maybe the games didn't use the other depth-compare modes too often?
Around 3 de10nano for AML 😅
Yeah, it's not ideal atm. lol
Doesn't help that just the inTri and interp blocks alone, are using about 30,000 Logic Elements.
I'm so convinced there are maths tricks which could be done to massively reduce the logic.
But I don't know enough about it, to say the least.
Asking AI doesn't help, as most of them have the IQ of a Carrot.
I think the Z-buffer might have to be done with a BRAM block, with a really wide input/output data bus.
For 48-bits per entry, and 32 "pixels" wide.
It would need to be 1,536 bits wide.
Don't think the IP blocks in Quartus can even do "byte enables" which are more than 8-bits wide, though.
Or, I'll just have to split it into 32 instances of BRAM.
Ooh, that's a BIG improvement already.
So yep, it's probably mainly the Z-buffer, hogging all of the registers.
Sim still works with that change, so... another Quartus compile.
A mux on the output, to chose the Column.
With row select chosing the entry within each column.
So each z_col array, is like a thin vertical strip of 32 pixels.
Well, Z-values + Prim_tag values.
row_sel is then like the "address".
OK, so the Z Buffer thing is using very little logic now, as expected.
So it's likely the parameter cache which is still using tons.
The inTri, and the three interp blocks are using around 14,400 ALMs.
Which is roughly 40,000 LEs. 😮
Much better.
But, since I commented out the Parameter cache stuff, Quartus is probably culling a lot of other stuff, too.
I just have to keep chipping away a it, and forcing it to use BRAMs instead of inferred RAMs.
I will eventually get around to drawing some diagrams about how some of this stuff works.
@rain obsidian You should give lectures on streams or something, I could watch/listen all day. Great stuff.
Still here. Still doing compiles. lol
It's only rendering garbage into one tile atm, as the Parameter buffer wasn't in place.
Not sure why it's not moving to the next tile yet, but I changed lots of code, so I'm in the debugging phase again.
I added some signals to SignalFlap, which should help me figure it out.
This next compile should tell me if the param buffer is going to fit.
If it does, this could be the first time the FPGA version has the potential to render with very good frame times.
But it won't be able to take advantage of that until the DDR burst transfers stuff is added.
Only using 71% of the FPGA logic atm.
If only that were true, though. lol
Because I'm certain there is a bug atm, which means it's not reading the Region Array (tile array) entries properly..
And Quartus will be culling quite a lot of logic due to that.
Right now, I only have a red square (tile) at the top-left of the screen, but that's it.
Trying to fix that now.
(the rest of the image is from the reicast VRAM dump, so that doesn't count.)
Normally, the Verilog would be rendering the tiles, and overwriting the existing image.
Yeah, it's trying to do a "render_to_tile" right away, which is wrong.
Normally it would do multiple "render_poly" pulses, to render each primitive into the Z / Tag buffer.
Then, after all prims have been processed, the Tag buffer ends up with all the info to render the whole tile.
So that does all of the Hidden Surface Removal.
Then it should do "render_to_tile" at the end, incrementing through each Tag "pixel" in turn, grabbing the actual texel (if needed), and outputting the final pixel colour.
The only reason it would normally trigger "render_to_tile" too early, is if it's seeing the eol (End of List) flag in the Object List.
So I probably don't have some DDR bus hooked up correctly atm.
(it's also not incrementing to the next tile on the screen, so it's definitely not reading the Region Array correctly.)
If I zoom in a bit, you can see the very first thing it does, which is done by the ra_parser module...
The REGION_BASE register in the GPU tells it where to find the Region Array entries.
Each RA entry contains only six 32-bit words.
Which has a Control word, followed by five other words for each possible Prim type it can render to the current tile.
(Opaque, Punchthrough, Op/PT Volume Modifier, Transparent, Transparent Volume Modifier.)
Each of those words gives you a VRAM address to look up the actual polygon ISP/TSP/TCW words, and the vertex params.
(it doesn't necessarily have to use all of the prim types. It's just whatever the CPU wants to display, and whichever prims exist within each tile.)
I can see that REGION_BASE is at 0x1667C0 in VRAM, as that's the first address being output on vram_addr.[23:0].
I check that against the sim.
The core loads the BIOS menu VRAM dump, by default...
Again, and I have to state this VERY time. That image above is a pre-render from reicast, not the core (yet). lol
The yellow tile at the top-left is due to the bug.
Can tally the results from SignalTap with the sim. Looking mainly at the ra_parser window atm.
I think I found the main issue already...
Some of this stuff is kind of a copy and paste from the sim code.
I really should merge both projects. lol
Then add things like DDR3 latency simulation.
Basically, it's pulsing ra_vram_rd twice, because it's jumping back to ra_state 10 instead of 11.
And that messes up the sequence of events, because you always have to follow every Read request with a wait for "vram_valid".
vram_valid comes direct from DDRAM_DOUT_READY, from the DDR3 controller.
(which tells you when the data is valid/ready, because DDR3 latency sucks ballz.)
Also, that issue with it doing the eol thing, is correct anyway.
The first entry in the opb_word table is 0xF0000000, so it should just ignore that, then move to the next entry.
(same thing happens in the sim, but then actual polygon entries follow on after that.)
Oh, and I was never incrementing prim_tag, so that doesn't help. lol
prim_tag is just a counter that should increment on each incoming primitive.
A primitive is just a collection of triangles, often in a triangle strip, or quad (pair).
It does move on to the next OL entry.
Then opb_word becomes 0xCA800000.
The upper three bits [31:29] determine what that means...
if (!opb_word[31]) begin // Triangle Strip.
poly_addr <= (PARAM_BASE&24'hf00000)+{opb_word[20:0], 2'b00};
if (isp_idle) begin
render_poly <= 1'b1;
ra_state <= ra_state + 8'd1;
end
end
else if (opb_word[31:29]==3'b100) begin // Triangle Array.
poly_addr <= (PARAM_BASE&24'hf00000)+{opb_word[20:0], 2'b00};
if (isp_idle) begin
render_poly <= 1'b1;
ra_state <= ra_state + 8'd1;
end
end
else if (opb_word[31:29]==3'b101) begin // Single Quad, or Quad Array.
poly_addr <= (PARAM_BASE&24'hf00000)+{opb_word[20:0], 2'b00};
if (isp_idle) begin
render_poly <= 1'b1;
ra_state <= ra_state + 8'd1;
end
end
else if (opb_word[31:29]==3'b111) begin // Pointer Block Link.
Whenever bit [31] of opb_word is Low, it denotes a triangle strip.
(which overrides all of the other cases, since they have bit [31] set High.)
A Pointer Block Link just contains the VRAM address for it to jump to, to continue reading more prims to render into the current tile, or maybe another PBL.
You rule. Seriously.
Thanks. 😉
Actually, I don't know what that opb_word is. It's not valid. lol
Probably due to it pulsing ra_vram_rd twice atm.
OK, it is trying to render some polys, but the other bugs are screwing it up.
x_ps (screen X pixel coord) is going crazy as well, and trying to draw completely outside of the screen. lol
Need to recompile. I think it's just that ra_state bug.
If this next compile renders ANYTHING reasonable, I'll be very happy.
It will be another big milestone in getting the PVR stuff done.
Yeah, it was even reading that same 0xCA800000 word into all of the ISP/TSP/TCW params, which is not good.
Oh well. Another ~25 minute wait.
Testing the fixed ra_parser code in the sim...
Now that the code from both the FPGA and sim versions are much more similar, I can copy (some) whole Verilog files between the two.
If anything else is broken in the core after this next compile, it's likely in the isp parser.
Nope, still broken.
OK, I see now.
It reads the lower 21 bits of opb_word, to find the VRAM address of the actual polygon vertex params.
But that's being shifted left somewhere, by two bits.
else if (strip_cnt < 6) begin // Check strip_mask bits 0 through 5...
if (strip_mask[strip_cnt]) begin
isp_vram_addr <= poly_addr; // Always use the absolute start address of the poly. Will fetch ISP/TSP/TCW again, but then skip verts.
poly_addr is being used directly, so as the BYTE address.
From the RA parser...
if (!opb_word[31]) begin // Triangle Strip.
poly_addr <= (PARAM_BASE&24'hf00000)+{opb_word[20:0], 2'b00};
if (isp_idle) begin
render_poly <= 1'b1;
ra_state <= ra_state + 8'd1;
end
end