Jump to content
PeteE

Copper (raster tech demo)

Recommended Posts

I was inspired by the C64 demo in this post and decided to port it to the 99/4a.  The lack of colors was indeed a struggle, but I think it turned out pretty okay given the limitations.  There are three major effects that are combined to produce the various animations.  The first is color cycling, which changes the contents of the color table to create motion.  The second is 8 rotating color bars on screen at 64 different angles, done by changing the pattern table address.  The final effect is the interleaved screen+color tables - using raster horizontal sync, which changes the screen image table address and color table address on every line.  This is using VDP graphics 1 color mode!

 

I've only tested it working in Classic99 and on a NTSC 99/4a console.  It wasn't working in JS99er or MAME, maybe because it relies on the VDP status collision flag being set by transparent (color 0) sprites?

copper8.bin

  • Like 9
  • Thanks 4

Share this post


Link to post
Share on other sites
1 hour ago, PeteE said:
I was inspired by the C64 demo in this post and decided to port it to the 99/4a.  The lack of colors was indeed a struggle, but I think it turned out pretty okay given the limitations.  There are three major effects that are combined to produce the various animations.  The first is color cycling, which changes the contents of the color table to create motion.  The second is 8 rotating color bars on screen at 64 different angles, done by changing the pattern table address.  The final effect is the interleaved screen+color tables - using raster horizontal sync, which changes the screen image table address and color table address on every line.  This is using VDP graphics 1 color mode!
 
I've only tested it working in Classic99 and on a NTSC 99/4a console.  It wasn't working in JS99er or MAME, maybe because it relies on the VDP status collision flag being set by transparent (color 0) sprites?
copper8.bin

cool.gif

Simply amazing dude!  here's it running on my 4/a.. 

 

 

  • Like 5

Share this post


Link to post
Share on other sites

To fix this... 

 

...when it happens, you need to find the H-HOLD adjustment on the back of your TV. It's a coil with a multi-turn slug. You will have to turn this several or more times, to get the picture to "unfold".

 

Than the COLOR BARS will appear correctly.:rolling:

  • Like 1
  • Haha 8

Share this post


Link to post
Share on other sites
1 hour ago, arcadeshopper said:



Simply amazing dude!  here's it running on my 4/a.. 

 

 

Thanks for posting the video!  I am curious - does it work with the F18A?  I'm pretty sure it won't work on a PAL console - I would need access to one to adjust the raster timing loop.

Share this post


Link to post
Share on other sites

Wow, it is impressive PeteE!
 

42 minutes ago, PeteE said:

[...] I'm pretty sure it won't work on a PAL console - I would need access to one to adjust the raster timing loop.

I don't know if raster timing loop is perfect but I can confirm it works on PAL console too :)

  • Like 3

Share this post


Link to post
Share on other sites
17 minutes ago, ti99iuc said:

Wow, it is impressive PeteE!
 

I don't know if raster timing loop is perfect but I can confirm it works on PAL console too :)

Oh really?  That's great.  On a PAL console, it will run at 25fps instead of 30fps.

  • Like 1

Share this post


Link to post
Share on other sites

It should run on the F18A, the raster effects tend to work fine there. I can't test it myself atm...

 

  • Like 1

Share this post


Link to post
Share on other sites

I confirm, in MAME, only the first seconds show correctly (until 0:08 in the video), the first three stripe displays. I cannot tell why it fails after that because I don't know the technique behind it. The 9918 emulation in MAME has been known to be quite precise, considering that the previous demos like Don't Mess with Texas run flawlessly, but I am not the author of the 9918 emulation.

 

@PeteE Maybe you can provide a simple sample program that should show a particular behavior so that I can test it, and we can find out the issue behind it.

 

Edit: It fails because the program crashes; I am getting this error:

[:gromport:single:cartridge] Set ROM page = 30 (writing to 603c)
[:maincpu] ** 601a: Illegal opcode 0000

 

which means that the cartridge space is not correctly mapped. I used paged378 for it, that is, writing to 6000 + i*2 maps page i into 6000-7FFF (for i=0..63). Everything works well until this switch.

 

In fact, page 30 is far beyond the cartridge space (128K).

Edited by mizapf
  • Like 2

Share this post


Link to post
Share on other sites
13 hours ago, PeteE said:

It wasn't working in JS99er ...

Fixed, but still not working in the F18A emulation.

Share this post


Link to post
Share on other sites
33 minutes ago, Asmusr said:

Fixed, but still not working in the F18A emulation.

Thanks!  The file f18a.ts still has

if (sprColor !== 0)

in two places.

I will need to come up with a better test for measuring the VDP clock rate compared to the CPU clock rate.

Share this post


Link to post
Share on other sites
8 hours ago, mizapf said:

I confirm, in MAME, only the first seconds show correctly (until 0:08 in the video), the first three stripe displays. I cannot tell why it fails after that because I don't know the technique behind it. The 9918 emulation in MAME has been known to be quite precise, considering that the previous demos like Don't Mess with Texas run flawlessly, but I am not the author of the 9918 emulation.

 

@PeteE Maybe you can provide a simple sample program that should show a particular behavior so that I can test it, and we can find out the issue behind it.

 

Edit: It fails because the program crashes; I am getting this error:

[:gromport:single:cartridge] Set ROM page = 30 (writing to 603c)
[:maincpu] ** 601a: Illegal opcode 0000

 

which means that the cartridge space is not correctly mapped. I used paged378 for it, that is, writing to 6000 + i*2 maps page i into 6000-7FFF (for i=0..63). Everything works well until this switch.

 

In fact, page 30 is far beyond the cartridge space (128K).

The page mapping wraps at the end of the cartridge image for Classic99 and FinalGROM99, for other ROM carts you would repeat the image to fill the ROM.  But it was a mistake, I forgot to mask of the uppermost bit of the angle register when calculating the bank, taking advantage of the last 32 angles are mirrored from the first 32 but with the colors reversed.

Share this post


Link to post
Share on other sites
10 minutes ago, PeteE said:

Thanks!  The file f18a.ts still has

if (sprColor !== 0)

in two places.

Yes but it won't work even if I remove that line, because my F18A emulation is hacky and calculates one sprite collision flag for the entire screen.

Share this post


Link to post
Share on other sites
31 minutes ago, PeteE said:

The page mapping wraps at the end of the cartridge image for Classic99 and FinalGROM99, for other ROM carts you would repeat the image to fill the ROM.  But it was a mistake, I forgot to mask of the uppermost bit of the angle register when calculating the bank, taking advantage of the last 32 angles are mirrored from the first 32 but with the colors reversed.

Wouldn't a real cart with a 27C010 (128 KiB) also wrap around?

Share this post


Link to post
Share on other sites
6 minutes ago, Asmusr said:

Wouldn't a real cart with a 27C010 (128 KiB) also wrap around?

I am not sure about that, and have to rely on what the owners of the real thing observe. If a single chip is used, we'll get a wrap-around, but not if several chips are used because the chip select may get lost. Either way, it is not a big deal to fix it in MAME.

Share this post


Link to post
Share on other sites

Great demo! Thank you!

Works on the TIny-99/4Av2 🙂 In some animation stages, I just notice a blinking vertical artefact line on the left of the screen.

It is the second time I see a compatibility problem with the computer (the first is for Tutankam, the game doesn't works). The problem is minor but I have to find what is wrong with it.

http://www.ti99.com/misc/test-copper-tiny994av2.mp4

Edited by fabrice montupet
  • Like 1

Share this post


Link to post
Share on other sites

OK, it runs on MAME if I add the page wrap. Also, I ran it on MAME 60Hz and 50 Hz, and both differ by the run time only: 120 sec vs. 144 secs.

So may I assume that the paged378 cartridges have a page wrap for smaller ROMs?

Share this post


Link to post
Share on other sites

This is the test program I used to verify the timing loop on the hsync.  On physical hardware 9918A, it should look like this:WIN_20201217_12_09_05_Pro.thumb.jpg.6da7076aaef2604d12e4e593067f8d60.jpg

 

The "T" on the left are the sprites used for collision detect.  The white band is achieved by setting the background color register to white, then immediately back to black.  The 'S' and 'D' keys can be used to move the sprite stack left or right.  Note: The white band won't be visible in emulation unless the background color register changes are tracked mid-scanline... 

 

The top of the "T" is used to catch the first sprite collision, then enters a cycle-tuned loop which checks the collision flag as close as possible to when it occurs: the flag is copied the EQ status bit, then a "JEQ $+2" instruction allows the timing to be adjusted.  If the EQ status is set, it is early and the collision hasn't ocurred yet, the jump is taken (consuming 10 cpu cycles.)  If the EQ status is clear, it is late and the collision has occurred, so the jump is not taken (8 cpu cycles.)

 

For the demo, the invisible sprite stack is positioned so that the white band is hidden just off the right side of the screen, making the register changes invisible (during hblank: the time the electron beam is scanning from the end of one scanline to the start of the next.)  In Fabrice's recording, the timing must be a little late, and the VDP has started drawing each line before all the registers are updated.

 

Source code (use xas99.py to assemble)

Spoiler
VDPWD  EQU  >8C00             ; VDP write data
VDPWA  EQU  >8C02             ; VDP set read/write address
VDPRD  EQU  >8800             ; VDP read data (don't forget NOP after address)
VDPSTA EQU  >8802             ; VDP status
VDPWM  EQU  >4000             ; VDP address write mask
VDPRM  EQU  >8000             ; VDP address register mask


       AORG >6000         ; Cartridge header in all banks
******************************************
       BANK ALL
******************************************
HEADER
       BYTE >AA     ; Standard header
       BYTE >01     ; Version number 1
       BYTE >01     ; Number of programs (optional)
       BYTE >00     ; Reserved (for FG99 this can be G,R,or X)
       DATA >0000   ; Pointer to power-up list
       DATA PRGLST  ; Pointer to program list
       DATA >0000   ; Pointer to DSR list
       DATA >0000   ; Pointer to subprogram list

PRGLST DATA >0000   ; Next program list entry
       DATA START   ; Program address
       BYTE CRTNME-CRTNM       ; Length of name
CRTNM  TEXT 'RASTER TEST'
CRTNME
       EVEN



WRKSP  EQU  >8300             ; Workspace memory in fast RAM
R0LB   EQU  WRKSP+1           ; Register zero low byte address
R1LB   EQU  WRKSP+3           ; Register zero low byte address
R2LB   EQU  WRKSP+5           ; Register zero low byte address



START
       LIMI 0
       LWPI WRKSP

       LI R14,VDPWA
       LI R15,VDPWD

       ; Initialize VDP registers
       LI R1,VDPINI
       LI R0,VDPRM     ; Register mask
!      MOVB *R1+,*R14  ; Write register data
       MOVB R0,*R14    ; Write register number
       AI R0,>100
       CI R0,>800+VDPRM
       JL -!

       LI R0,CLRTAB
       LI R1,CLRSET      ; color table
       LI R2,32
       BL @VDPW

       LI R0,SPRPAT
       LI R1,SPR0      ; sprite patterns
       LI R2,32*3
       BL @VDPW

       LI R0,SPRTAB
       LI R1,SL0        ; sprite list
       LI R2,(13*2*4)+4
       BL @VDPW

       LI R0,FastFunc        ; copy fast RAM func into fast RAM
       LI R1,FastFuncStart
       LI R2,FastFuncSize/2
!      MOV *R0+,*R1+
       DEC R2
       JNE -!

       LI R6,X

mainloop

       BL @x#FastFuncStart  ; modifies R12

       LI R1,>0100
       LI R12,>0024
       LDCR R1,3
       LI R12,>0006
       TB 5    ; S
       JNE MoveLeft

       LI R1,>0200
       LI R12,>0024
       LDCR R1,3
       LI R12,>0006
       TB 5    ; D
       JNE MoveRight

       JMP mainloop

MoveLeft
       DECT R6
MoveRight
       INC R6
       ANDI R6,>00FF

       MOV R6,R1
       SWPB R1
       AI R1,->1000

       LI R0,SPRTAB+VDPWM+1 ; Sprite X coordinates
       BL @VDPWB
       AI R0,4
       BL @VDPWB
       AI R1,>1000

       LI R2,24
!
       AI R0,4
       BL @VDPWB
       DEC R2
       JNE -!

       JMP mainloop





* Copy R2 bytes from R1 to VDP address R0
VDPW   MOVB @R0LB,*R14      ; Send low byte of VDP RAM write address
       ORI  R0,VDPWM        ; Set read/write bits 14 and 15 to write (01)
       MOVB R0,*R14         ; Send high byte of VDP RAM write address
!      MOVB *R1+,*R15       ; Write byte to VDP RAM
       DEC  R2              ; Byte counter
       JNE  -!              ; Check if done
       RT


* Copy byte in R1 to VDP address R0
VDPWB  MOVB @R0LB,*R14      ; Send low byte of VDP RAM write address
       ORI  R0,VDPWM        ; Set read/write bits 14 and 15 to write (01)
       MOVB R0,*R14         ; Send high byte of VDP RAM write address
       MOVB R1,*R15         ; Write byte to VDP RAM
       RT


SCRTAB EQU >0000    ; >300 bytes
SPRTAB EQU >0380    ;  >80 bytes
CLRTAB EQU >0300    ;  >20 bytes
SPRPAT EQU >1800    ; >800 bytes
PATTAB0 EQU >0000    ; >800 bytes, from >380
PATTAB1 EQU >0800    ; >800 bytes, from >B80
PATTAB2 EQU >1000    ; >800 bytes, from >1380
PATTAB3 EQU >1800    ; >800 bytes, from >1B80
PATTAB4 EQU >2000    ; >800 bytes
PATTAB5 EQU >2800    ; >800 bytes
PATTAB6 EQU >3000    ; >800 bytes
PATTAB7 EQU >3800    ; >800 bytes


VDPINI
       BYTE >00          ; VDP Register 0: 00
       BYTE >E2          ; VDP Register 1: 16x16 Sprites
       BYTE (SCRTAB/>400); VDP Register 2: Screen Image Table
       BYTE (CLRTAB/>40)+>00 ; VDP Register 3: Color Table
       BYTE (PATTAB1/>800)+>0; VDP Register 4: Pattern Table
       BYTE (SPRTAB/>80) ; VDP Register 5: Sprite List Table
       BYTE (SPRPAT/>800); VDP Register 6: Sprite Pattern Table
       BYTE >F1          ; VDP Register 7: White on Black

SPR0   ; 1-pixel wide vertical line sprite
       DATA >0000,>0000,>0000,>0000,>0000,>0000,>0000,>0000,>8080,>8080,>8080,>8080,>8080,>8080,>8080,>8080
       DATA >FF00,>0000,>0000,>0000,>0000,>0000,>0000,>0000,>FF80,>8080,>8080,>8080,>8080,>8080,>8080,>8080
       DATA >FF00,>0000,>0000,>0000,>0000,>0000,>0000,>0000,>FF00,>0000,>0000,>0000,>0000,>0000,>0000,>0000

X      EQU >0020
SCOLOR EQU >000F
SL0
       DATA >FF00+X-16,>0800+SCOLOR,>FF00+X-16,>0800
       DATA >FF00+X,>0400+SCOLOR,>FF00+X,>0400
       DATA >0F00+X,SCOLOR,>0F00+X,>0000
       DATA >1F00+X,SCOLOR,>1F00+X,>0000
       DATA >2F00+X,SCOLOR,>2F00+X,>0000
       DATA >3F00+X,SCOLOR,>3F00+X,>0000
       DATA >4F00+X,SCOLOR,>4F00+X,>0000
       DATA >5F00+X,SCOLOR,>5F00+X,>0000
       DATA >6F00+X,SCOLOR,>6F00+X,>0000
       DATA >7F00+X,SCOLOR,>7F00+X,>0000
       DATA >8F00+X,SCOLOR,>8F00+X,>0000
       DATA >9F00+X,SCOLOR,>9F00+X,>0000
       DATA >AF00+X,SCOLOR,>AF00+X,>0000
       DATA >D000,>0000,>D000,>0000

CLRSET
       DATA >F0F0,>F0F0,>F0F0,>F0F0,>F0F0,>F0F0,>F0F0,>F0F0
       DATA >F0F0,>F0F0,>F0F0,>F0F0,>F0F0,>F0F0,>F0F0,>F0F0


* Modifies R12 only
FastFunc
       XORG >8320
FastFuncStart
       LI R12,192      ; scanline counter

       LWPI VDPWA      ; 10 make R0 reference VDPWA
       LI R0,>1100     ; 16
       LI R0,>0700+VDPRM  ; 16 border color register

       LWPI VDPSTA     ; 10 make R0 reference VDPSTA
!
       ANDI R0,>2000   ; 22 read collision flag into EQ
       JEQ -!          ; 10/8
       JMP !

FastFuncLoop0
       LWPI VDPSTA     ; 10 make R0 reference VDPSTA
       ANDI R0,>2000   ; 22 read collision flag into EQ
       JEQ $+2         ; 10/8

       NOP            ; 10
       NOP            ; 10
!
       LWPI VDPWA      ; 10 make R0 reference VDPWA
       LI R0,>FF00     ; 16
       LI R0,>0700+VDPRM  ; 16 border color register
       LI R0,>F100     ; 16
       LI R0,>0700+VDPRM  ; 16 border color register

       LWPI VDPSTA     ; 10 make R0 reference VDPSTA
       ANDI R0,>2000   ; 22 read collision flag into EQ

       JNE $+2        ; 8
       CLR R2         ; 14
       NOP            ; 10

       ANDI R0,>2000   ; 22 read collision flag into EQ
       JEQ $+2         ; 10/8

       NOP            ; 10
       NOP            ; 10

       LWPI VDPWA      ; 10 make R0 reference VDPWA
       LI R0,>FF00     ; 16
       LI R0,>0700+VDPRM  ; 16 border color register
       LI R0,>F100     ; 16
       LI R0,>0700+VDPRM  ; 16 border color register

       JEQ $+2        ; 8
       JEQ $+2        ; 8
       NOP            ; 10

       LWPI WRKSP     ; 10

       DECT R12         ; 10
       JNE FastFuncLoop0  ; 10/8

Vsync
       CLR R12               ; CRU Address bit 0002 - VDP INT
!      TB 2                  ; CRU bit 2 - VDP INT
       JEQ -!                ; Loop until set
       MOVB @VDPSTA,R12      ; Clear interrupt flag manually since we polled CRU


       RT

FastFuncEnd

FastFuncSize EQU (FastFuncEnd-FastFuncStart)

 

rasterc.bin

  • Like 2

Share this post


Link to post
Share on other sites
5 hours ago, Asmusr said:

Wouldn't a real cart with a 27C010 (128 KiB) also wrap around?

Yes, it will. Address pins which are not connected are "don't care".

 

But MAME is the most accurate emulator, therefore it is Classic99 and real hardware which is wrong. ;)

 

  • Haha 4

Share this post


Link to post
Share on other sites
3 hours ago, mizapf said:

OK, it runs on MAME if I add the page wrap. Also, I ran it on MAME 60Hz and 50 Hz, and both differ by the run time only: 120 sec vs. 144 secs.

So may I assume that the paged378 cartridges have a page wrap for smaller ROMs?

Less teasingly, yes, you'll have to. Smaller ROMs don't have any higher address pins to respond to, and the decode is happening on the ROM chip itself, plus the latch. Any bits missing in the middle are literally not connected, so it doesn't matter if they are high or low.

 

Share this post


Link to post
Share on other sites
3 hours ago, PeteE said:

This is the test program I used to verify the timing loop on the hsync.  On physical hardware 9918A, it should look like this:WIN_20201217_12_09_05_Pro.thumb.jpg.6da7076aaef2604d12e4e593067f8d60.jpg

 

The "T" on the left are the sprites used for collision detect.  The white band is achieved by setting the background color register to white, then immediately back to black.  The 'S' and 'D' keys can be used to move the sprite stack left or right.  Note: The white band won't be visible in emulation unless the background color register changes are tracked mid-scanline... 

 

The top of the "T" is used to catch the first sprite collision, then enters a cycle-tuned loop which checks the collision flag as close as possible to when it occurs: the flag is copied the EQ status bit, then a "JEQ $+2" instruction allows the timing to be adjusted.  If the EQ status is set, it is early and the collision hasn't ocurred yet, the jump is taken (consuming 10 cpu cycles.)  If the EQ status is clear, it is late and the collision has occurred, so the jump is not taken (8 cpu cycles.)

 

For the demo, the invisible sprite stack is positioned so that the white band is hidden just off the right side of the screen, making the register changes invisible (during hblank: the time the electron beam is scanning from the end of one scanline to the start of the next.)  In Fabrice's recording, the timing must be a little late, and the VDP has started drawing each line before all the registers are updated.

 

Source code (use xas99.py to assemble)

  Reveal hidden contents

VDPWD  EQU  >8C00             ; VDP write data
VDPWA  EQU  >8C02             ; VDP set read/write address
VDPRD  EQU  >8800             ; VDP read data (don't forget NOP after address)
VDPSTA EQU  >8802             ; VDP status
VDPWM  EQU  >4000             ; VDP address write mask
VDPRM  EQU  >8000             ; VDP address register mask


       AORG >6000         ; Cartridge header in all banks
******************************************
       BANK ALL
******************************************
HEADER
       BYTE >AA     ; Standard header
       BYTE >01     ; Version number 1
       BYTE >01     ; Number of programs (optional)
       BYTE >00     ; Reserved (for FG99 this can be G,R,or X)
       DATA >0000   ; Pointer to power-up list
       DATA PRGLST  ; Pointer to program list
       DATA >0000   ; Pointer to DSR list
       DATA >0000   ; Pointer to subprogram list

PRGLST DATA >0000   ; Next program list entry
       DATA START   ; Program address
       BYTE CRTNME-CRTNM       ; Length of name
CRTNM  TEXT 'RASTER TEST'
CRTNME
       EVEN



WRKSP  EQU  >8300             ; Workspace memory in fast RAM
R0LB   EQU  WRKSP+1           ; Register zero low byte address
R1LB   EQU  WRKSP+3           ; Register zero low byte address
R2LB   EQU  WRKSP+5           ; Register zero low byte address



START
       LIMI 0
       LWPI WRKSP

       LI R14,VDPWA
       LI R15,VDPWD

       ; Initialize VDP registers
       LI R1,VDPINI
       LI R0,VDPRM     ; Register mask
!      MOVB *R1+,*R14  ; Write register data
       MOVB R0,*R14    ; Write register number
       AI R0,>100
       CI R0,>800+VDPRM
       JL -!

       LI R0,CLRTAB
       LI R1,CLRSET      ; color table
       LI R2,32
       BL @VDPW

       LI R0,SPRPAT
       LI R1,SPR0      ; sprite patterns
       LI R2,32*3
       BL @VDPW

       LI R0,SPRTAB
       LI R1,SL0        ; sprite list
       LI R2,(13*2*4)+4
       BL @VDPW

       LI R0,FastFunc        ; copy fast RAM func into fast RAM
       LI R1,FastFuncStart
       LI R2,FastFuncSize/2
!      MOV *R0+,*R1+
       DEC R2
       JNE -!

       LI R6,X

mainloop

       BL @x#FastFuncStart  ; modifies R12

       LI R1,>0100
       LI R12,>0024
       LDCR R1,3
       LI R12,>0006
       TB 5    ; S
       JNE MoveLeft

       LI R1,>0200
       LI R12,>0024
       LDCR R1,3
       LI R12,>0006
       TB 5    ; D
       JNE MoveRight

       JMP mainloop

MoveLeft
       DECT R6
MoveRight
       INC R6
       ANDI R6,>00FF

       MOV R6,R1
       SWPB R1
       AI R1,->1000

       LI R0,SPRTAB+VDPWM+1 ; Sprite X coordinates
       BL @VDPWB
       AI R0,4
       BL @VDPWB
       AI R1,>1000

       LI R2,24
!
       AI R0,4
       BL @VDPWB
       DEC R2
       JNE -!

       JMP mainloop





* Copy R2 bytes from R1 to VDP address R0
VDPW   MOVB @R0LB,*R14      ; Send low byte of VDP RAM write address
       ORI  R0,VDPWM        ; Set read/write bits 14 and 15 to write (01)
       MOVB R0,*R14         ; Send high byte of VDP RAM write address
!      MOVB *R1+,*R15       ; Write byte to VDP RAM
       DEC  R2              ; Byte counter
       JNE  -!              ; Check if done
       RT


* Copy byte in R1 to VDP address R0
VDPWB  MOVB @R0LB,*R14      ; Send low byte of VDP RAM write address
       ORI  R0,VDPWM        ; Set read/write bits 14 and 15 to write (01)
       MOVB R0,*R14         ; Send high byte of VDP RAM write address
       MOVB R1,*R15         ; Write byte to VDP RAM
       RT


SCRTAB EQU >0000    ; >300 bytes
SPRTAB EQU >0380    ;  >80 bytes
CLRTAB EQU >0300    ;  >20 bytes
SPRPAT EQU >1800    ; >800 bytes
PATTAB0 EQU >0000    ; >800 bytes, from >380
PATTAB1 EQU >0800    ; >800 bytes, from >B80
PATTAB2 EQU >1000    ; >800 bytes, from >1380
PATTAB3 EQU >1800    ; >800 bytes, from >1B80
PATTAB4 EQU >2000    ; >800 bytes
PATTAB5 EQU >2800    ; >800 bytes
PATTAB6 EQU >3000    ; >800 bytes
PATTAB7 EQU >3800    ; >800 bytes


VDPINI
       BYTE >00          ; VDP Register 0: 00
       BYTE >E2          ; VDP Register 1: 16x16 Sprites
       BYTE (SCRTAB/>400); VDP Register 2: Screen Image Table
       BYTE (CLRTAB/>40)+>00 ; VDP Register 3: Color Table
       BYTE (PATTAB1/>800)+>0; VDP Register 4: Pattern Table
       BYTE (SPRTAB/>80) ; VDP Register 5: Sprite List Table
       BYTE (SPRPAT/>800); VDP Register 6: Sprite Pattern Table
       BYTE >F1          ; VDP Register 7: White on Black

SPR0   ; 1-pixel wide vertical line sprite
       DATA >0000,>0000,>0000,>0000,>0000,>0000,>0000,>0000,>8080,>8080,>8080,>8080,>8080,>8080,>8080,>8080
       DATA >FF00,>0000,>0000,>0000,>0000,>0000,>0000,>0000,>FF80,>8080,>8080,>8080,>8080,>8080,>8080,>8080
       DATA >FF00,>0000,>0000,>0000,>0000,>0000,>0000,>0000,>FF00,>0000,>0000,>0000,>0000,>0000,>0000,>0000

X      EQU >0020
SCOLOR EQU >000F
SL0
       DATA >FF00+X-16,>0800+SCOLOR,>FF00+X-16,>0800
       DATA >FF00+X,>0400+SCOLOR,>FF00+X,>0400
       DATA >0F00+X,SCOLOR,>0F00+X,>0000
       DATA >1F00+X,SCOLOR,>1F00+X,>0000
       DATA >2F00+X,SCOLOR,>2F00+X,>0000
       DATA >3F00+X,SCOLOR,>3F00+X,>0000
       DATA >4F00+X,SCOLOR,>4F00+X,>0000
       DATA >5F00+X,SCOLOR,>5F00+X,>0000
       DATA >6F00+X,SCOLOR,>6F00+X,>0000
       DATA >7F00+X,SCOLOR,>7F00+X,>0000
       DATA >8F00+X,SCOLOR,>8F00+X,>0000
       DATA >9F00+X,SCOLOR,>9F00+X,>0000
       DATA >AF00+X,SCOLOR,>AF00+X,>0000
       DATA >D000,>0000,>D000,>0000

CLRSET
       DATA >F0F0,>F0F0,>F0F0,>F0F0,>F0F0,>F0F0,>F0F0,>F0F0
       DATA >F0F0,>F0F0,>F0F0,>F0F0,>F0F0,>F0F0,>F0F0,>F0F0


* Modifies R12 only
FastFunc
       XORG >8320
FastFuncStart
       LI R12,192      ; scanline counter

       LWPI VDPWA      ; 10 make R0 reference VDPWA
       LI R0,>1100     ; 16
       LI R0,>0700+VDPRM  ; 16 border color register

       LWPI VDPSTA     ; 10 make R0 reference VDPSTA
!
       ANDI R0,>2000   ; 22 read collision flag into EQ
       JEQ -!          ; 10/8
       JMP !

FastFuncLoop0
       LWPI VDPSTA     ; 10 make R0 reference VDPSTA
       ANDI R0,>2000   ; 22 read collision flag into EQ
       JEQ $+2         ; 10/8

       NOP            ; 10
       NOP            ; 10
!
       LWPI VDPWA      ; 10 make R0 reference VDPWA
       LI R0,>FF00     ; 16
       LI R0,>0700+VDPRM  ; 16 border color register
       LI R0,>F100     ; 16
       LI R0,>0700+VDPRM  ; 16 border color register

       LWPI VDPSTA     ; 10 make R0 reference VDPSTA
       ANDI R0,>2000   ; 22 read collision flag into EQ

       JNE $+2        ; 8
       CLR R2         ; 14
       NOP            ; 10

       ANDI R0,>2000   ; 22 read collision flag into EQ
       JEQ $+2         ; 10/8

       NOP            ; 10
       NOP            ; 10

       LWPI VDPWA      ; 10 make R0 reference VDPWA
       LI R0,>FF00     ; 16
       LI R0,>0700+VDPRM  ; 16 border color register
       LI R0,>F100     ; 16
       LI R0,>0700+VDPRM  ; 16 border color register

       JEQ $+2        ; 8
       JEQ $+2        ; 8
       NOP            ; 10

       LWPI WRKSP     ; 10

       DECT R12         ; 10
       JNE FastFuncLoop0  ; 10/8

Vsync
       CLR R12               ; CRU Address bit 0002 - VDP INT
!      TB 2                  ; CRU bit 2 - VDP INT
       JEQ -!                ; Loop until set
       MOVB @VDPSTA,R12      ; Clear interrupt flag manually since we polled CRU


       RT

FastFuncEnd

FastFuncSize EQU (FastFuncEnd-FastFuncStart)

 

rasterc.bin 644 B · 6 downloads

That's impressive to see, even after everything we've already seen I still doubted that same-scanline response was possible. This finally changes my mind. ;)

 

  • Like 2
  • Thanks 2

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...