It is currently Fri Jul 19, 2019 9:49 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 59 posts ]  Go to page Previous  1, 2, 3, 4
Author Message
PostPosted: Sun Mar 17, 2019 8:51 pm 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 939
If you have a debugger, double check that your interrupt table contains correct addresses.
And in the interrupt handlers, insert a "jmp endlessloop" instead of trying to execute iret for now.
The hlt opcode shouldn't cause problems, or does it work when you remove that opcode?

A jump to 0 could be caused by interrupt table being zerofilled, or stack pointer pointing to zerofilled/readonly memory, though the ret from the palette function seems to have worked. But if it is a stack problem: look where sp points to after crash, and if there is anything currently stored on stack (or if there a still traces from values that were stored on stack).

That XA flag for 20bit vs 24bit addressing... I hope that won't affect the values in the irq table? Like automatically using 24bit mode for interrupts?


Top
 Profile  
 
PostPosted: Sun Mar 17, 2019 9:43 pm 
Offline
Formerly Espozo
User avatar

Joined: Mon Sep 15, 2014 4:35 pm
Posts: 3501
Location: Richmond, Virginia
I noticed there was one address that didn't match the others, so I changed that, and I even moved the function to the beginning of the interrupt handler section. From 0x00000 to 0x003FF in rom is now filled with "0x0040 0x0000", which should be 0x00400, which would be correct. I also replaced the iret instruction with a jump to itself, but if this were the problem, I should have seen the processor at least jump to the iret anyway.

Unfortunately, it still doesn't work, even if I remove the hlt instruction (the only difference is that I need to wait a ton of cycles for the interrupt to fire). Something strange though, is that the 0x0068 that gets pushed to the stack from the palette uploader function (which I verified is the correct value for IP) gets pushed down 4 bytes, with "0x0041 0xF246" taking the top of the stack, which doesn't seem correct, but it's not 0x00000. The processor is at 0x00478 when the interrupt occurs.


Top
 Profile  
 
PostPosted: Sun Mar 17, 2019 11:22 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 8486
Location: Seattle
Maybe somehow you are executing from 0x41:0x68 instead of 0x40:0x78 ... ?


Top
 Profile  
 
PostPosted: Sun Mar 17, 2019 11:32 pm 
Offline
Formerly Espozo
User avatar

Joined: Mon Sep 15, 2014 4:35 pm
Posts: 3501
Location: Richmond, Virginia
Those two should be equivalent, shouldn't they? CS starts and stays at 0x0041 until it (magically) gets wiped out. And I forgot to mention, the stack pointer goes from 0x0000, to 0xFFFE after the subroutine (and never goes back to 0x0000...) then goes to 0xFFFA after the interrupt is triggered.


Top
 Profile  
 
PostPosted: Sun Mar 17, 2019 11:50 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 8486
Location: Seattle
They're the same linear address, but they'll show up differently on the stack.


Top
 Profile  
 
PostPosted: Mon Mar 18, 2019 1:32 am 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 939
The stack content looks right, interrupts are pushing 3 words (flags and CS:IP).

Pushed CS being 41h for main program is also right (because the source code has interrupt code in a separate segment at CS=40h, and main at CS=41h, which is a bit weird, I would put all code into the same segment, unless your code grows bigger than 64K, of course).

The values in the interrupt table are "00 00 40 00", right? Just in case you get the little endian wrong or whatever.
And the values are still so at time of crash, right? Just in case your code or some DMA had destroyed them somehow.
If you have a copy of a working game, check if its interrupt table looks somehow different as expected.

Probably not the problem: But the interrupt table would need some work, I would add comments to each line, saying IRQ 00h, IRQ 01h, ..., IRQ FFh (and/or use something like REPT to fill a range of unused entries). And especially, add a ERRIF directive at the end of the table, throwing an error if the table size isn't 400h bytes.

Do you have an idea which interrupt is getting triggered? That would help to know what is happening.

Or better: Use the "int" opcode to manually trigger an interrupt, eg. "int 00h" should jump to the first interrupt table entry, that kind of software interrupts should work even if IRQs are disabled.

Oh, and I've read a bit about Irem M92... one webpage mentioned encrypted ROMs. And, as far as understand only some bytes here and there are being encrypted? If I got that right, then you might need to encrypt your ROM, or make sure that your emulator can deal with unencrypted ROMs.

Btw. is the code and interrupt table in ROM or RAM?


Top
 Profile  
 
PostPosted: Mon Mar 18, 2019 7:36 pm 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 939
https://en.m.wikipedia.org/wiki/NEC_V20 says that V33 vs V33A differ in terms of incompatble "interrupt vector numbers" (whatever that means), that might be a problem if M92 has V33 chips, or if some such boards have V33 and others have V33A.

https://patpend.net/technical/arcade/m92.html mentions a interrupt controller that is written to on bootup, you should probably do that, too. Just copy the init code from another game, maybe it'll help.

For the in/out opcodes, you are always using 16bit ax, is that that intended? The patpend doc isn't too clear about the port size(s), some might be supposed to be used with 8bit al, but, even if so, perhaps one could still access two ports at once via 16bit ax.


Top
 Profile  
 
PostPosted: Mon Mar 18, 2019 11:17 pm 
Offline
Formerly Espozo
User avatar

Joined: Mon Sep 15, 2014 4:35 pm
Posts: 3501
Location: Richmond, Virginia
Sorry for the late reply; I've been busy all day.

nocash wrote:
The values in the interrupt table are "00 00 40 00", right? Just in case you get the little endian wrong or whatever.

Correct.

nocash wrote:
And the values are still so at time of crash, right? Just in case your code or some DMA had destroyed them somehow.

Also correct; it's in rom, but I was paranoid enough to check if it changes somehow anyway, and sure enough, it doesn't.

nocash wrote:
ERRIF directive at the end of the table, throwing an error if the table size isn't 400h bytes.

Do you have an idea of how to do this? I wrote:

Code:
end_of_ivt:

%if (end_of_ivt > 0x400)
  %error Interrupt Vector Table over 1KB.
%endif


But yasm writes "error: non-constant value given to `%if'"

nocash wrote:
Do you have an idea which interrupt is getting triggered? That would help to know what is happening.

It should be vblank; it occurs right before "beam y" loops back to 0. I don't know the number of the interrupt though.

nocash wrote:
Oh, and I've read a bit about Irem M92... one webpage mentioned encrypted ROMs. And, as far as understand only some bytes here and there are being encrypted? If I got that right, then you might need to encrypt your ROM, or make sure that your emulator can deal with unencrypted ROMs.

That is only for the sound cpu program. I'm currently just using the files from Gunforce II for this.

nocash wrote:
says that V33 vs V33A differ in terms of incompatble "interrupt vector numbers" (whatever that means), that might be a problem if M92 has V33 chips, or if some such boards have V33 and others have V33A.

I have no idea, unfortunately.

nocash wrote:
mentions a interrupt controller that is written to on bootup, you should probably do that, too. Just copy the init code from another game, maybe it'll help.

Oh, wow, you're right... I'll see what's written to these in an actual game and replicate it in my code, and if that doesn't work, I'll go and step through the code and copy everything all the way up until the title screen, at which point everything appears to be initialized.

nocash wrote:
For the in/out opcodes, you are always using 16bit ax, is that that intended?

Oh, oops, that's not.


Top
 Profile  
 
PostPosted: Tue Mar 19, 2019 12:19 am 
Offline
Formerly Espozo
User avatar

Joined: Mon Sep 15, 2014 4:35 pm
Posts: 3501
Location: Richmond, Virginia
Holy shit, look what I finally got working though:

Attachment:
Sprite.png
Sprite.png [ 1.57 KiB | Viewed 4640 times ]


I really don't know why I couldn't get this to work last time I did this years ago, because it was pretty straightforward; all you have to do is give your sprite (I arbitrary chose the 32nd one) parameters like a nonzero y value so it actually shows up on screen as well as a nonzero tile number (unless tile 0 isn't blank).

Code:
;Enable Sprites
  mov ax, VIDEO_HARDWARE_RAM_START
  mov ds, ax
  mov word [spriteRam + 0x100], 0x0100
  mov word [spriteRam + 0x102], 0x0001
  mov word [spriteRam + 0x104], 0x0000
  mov word [spriteRam + 0x106], 0x0100
  xor ax, ax
  mov [spriteControlRam + 0], ax   ;sets up DMA
  mov [spriteControlRam + 4], ax   ;sets up DMA
  mov [spriteControlRam + 8], ax   ;DMA spriteRam


What was tripping me up is that patpend.net erroneously says 0xF9008 "Clears sprite ram" when all it does is DMA the copy of sprite ram to ram, and the MAME driver has it written like this

Code:
   COMBINE_DATA(&m_spritecontrol[offset]);
   // offset0: sprite list size (negative)
   // offset1: ? (always 0)
   // offset2: sprite control
   // offset3: ? (always 0)
   // offset4: sprite dma
   // offset5: ?


but the offset is really the offset * 2, because it's apparently by words.


Top
 Profile  
 
PostPosted: Mon Mar 25, 2019 12:15 am 
Offline
Formerly Espozo
User avatar

Joined: Mon Sep 15, 2014 4:35 pm
Posts: 3501
Location: Richmond, Virginia
Okay, getting interrupts to work properly was actually way easier than I expected; I just opened (the original) Gunforce II in MAME debugger, set watchpoints for IO 0x40 to 0x43, then copied exactly what was written to these registers in my code.

I have no idea what the meaning behind these values are, but if these registers are only written to at startup, I shouldn't have to worry. I'm also writing to the same register three times in a row, but I figure it's best not to tamper with it if I don't know how it works...

Code:
;Set Up Interrupt Controller (This is exactly what Gunforce II writes)
  mov al, 0x17
  out 0x40, al
  mov al, 0x20
  out 0x42, al
  mov al, 0x0F
  out 0x42, al
  mov al, 0x08
  out 0x42, al


A simple demo scrolling BG1 has been created. I should have everything (except sound, but that's the very last thing I care about) working now; this hardware is gloriously simple... Expect to see stuff in the future. I might create another thread showcasing this if it turns into a full fledged engine instead of just a demo.


Top
 Profile  
 
PostPosted: Mon Mar 25, 2019 9:46 am 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 8486
Location: Seattle
MAME says that the M92 apparently uses NEC's in-house clone (µPD70159, "Interrupt Control Unit") of the x86 PC's standard Programmable Interrupt Controller, the 8259.

The thing that's weird is that the 8259 has a single address line, and it's usually A0, so I'm a little confused why the code you've used as reference is using A1.

If it were instead
Code:
0x17→p[0x40] : write ICW1 (due to (address&1)==0 and (data&0x10)==0x40)
 - data&0xE0 - unused, 8085 only
 - data&0x08 - edge-triggered
 - data&0x04 - 8085 only? IRQ vectors are spaced every 4 bytes
 - data&0x02 - only one PIC is present (ICW3 will not be written)
 - data&0x01 - ICW4 will be written
0x20→p[0x41] : write ICW2
 - data&0xF8 - relay hardware IRQs to x86 IRQ vectors 0x20-0x27
 - data&0x07 - 8085 only
0x0F→p[0x41] : write ICW4
 - data&0xE0 - unused
 - data&0x10 - disable "special fully nested mode" or use "normal nest mode"
 - data&0x0C - primary/only PIC is using buffer mode
 - data&0x02 - "auto end-of-interrupt"
 - data&0x01 - x86 mode
0x08→p[0x41] : write OCW1
 - data&0x08 : only IRQ3 is disabled


Top
 Profile  
 
PostPosted: Mon Mar 25, 2019 3:17 pm 
Offline
Formerly Espozo
User avatar

Joined: Mon Sep 15, 2014 4:35 pm
Posts: 3501
Location: Richmond, Virginia
lidnariq wrote:
The thing that's weird is that the 8259 has a single address line, and it's usually A0, so I'm a little confused why the code you've used as reference is using A1.

What is A1? do you mean how I store the variables in register AL? I didn't copy the exact code, but I am writing the same values in the same order to these IO registers, so the behavior should be the same.


Top
 Profile  
 
PostPosted: Mon Mar 25, 2019 3:34 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 8486
Location: Seattle
Address Line 1, containing the "2s" bit of the address. In the XT, the 8259 there is configured at I/O space ports 20h and 21h; but the code you're using as reference is instead apparently referring to them at 40h and 42h.


Top
 Profile  
 
PostPosted: Mon Mar 25, 2019 3:42 pm 
Offline
Formerly Espozo
User avatar

Joined: Mon Sep 15, 2014 4:35 pm
Posts: 3501
Location: Richmond, Virginia
What I did, is I saw where interrupt control registers are located according to this: https://patpend.net/technical/arcade/m92.html, then set watchpoints for the IO write ports, then copied the behavior. It seems to work, somehow.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 59 posts ]  Go to page Previous  1, 2, 3, 4

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group