PeteE Posted December 17, 2020 Share Posted December 17, 2020 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 11 4 Quote Link to comment Share on other sites More sharing options...
+arcadeshopper Posted December 17, 2020 Share Posted December 17, 2020 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 Simply amazing dude! here's it running on my 4/a.. 6 Quote Link to comment Share on other sites More sharing options...
HOME AUTOMATION Posted December 17, 2020 Share Posted December 17, 2020 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. 1 8 Quote Link to comment Share on other sites More sharing options...
GDMike Posted December 17, 2020 Share Posted December 17, 2020 (edited) This is cool Edited December 17, 2020 by GDMike Quote Link to comment Share on other sites More sharing options...
Nick99 Posted December 17, 2020 Share Posted December 17, 2020 And the TI-99 continues to impress, Thanks @PeteE! 1 Quote Link to comment Share on other sites More sharing options...
PeteE Posted December 17, 2020 Author Share Posted December 17, 2020 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. Quote Link to comment Share on other sites More sharing options...
ti99iuc Posted December 17, 2020 Share Posted December 17, 2020 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 3 Quote Link to comment Share on other sites More sharing options...
PeteE Posted December 17, 2020 Author Share Posted December 17, 2020 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. 1 Quote Link to comment Share on other sites More sharing options...
Tursi Posted December 17, 2020 Share Posted December 17, 2020 It should run on the F18A, the raster effects tend to work fine there. I can't test it myself atm... 1 Quote Link to comment Share on other sites More sharing options...
+mizapf Posted December 17, 2020 Share Posted December 17, 2020 (edited) 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 December 17, 2020 by mizapf 2 Quote Link to comment Share on other sites More sharing options...
+arcadeshopper Posted December 17, 2020 Share Posted December 17, 2020 the demo does not work correctly on f18a Quote Link to comment Share on other sites More sharing options...
Asmusr Posted December 17, 2020 Share Posted December 17, 2020 13 hours ago, PeteE said: It wasn't working in JS99er ... Fixed, but still not working in the F18A emulation. Quote Link to comment Share on other sites More sharing options...
PeteE Posted December 17, 2020 Author Share Posted December 17, 2020 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. Quote Link to comment Share on other sites More sharing options...
PeteE Posted December 17, 2020 Author Share Posted December 17, 2020 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. Quote Link to comment Share on other sites More sharing options...
Asmusr Posted December 17, 2020 Share Posted December 17, 2020 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. Quote Link to comment Share on other sites More sharing options...
Asmusr Posted December 17, 2020 Share Posted December 17, 2020 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? Quote Link to comment Share on other sites More sharing options...
+mizapf Posted December 17, 2020 Share Posted December 17, 2020 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. Quote Link to comment Share on other sites More sharing options...
fabrice montupet Posted December 17, 2020 Share Posted December 17, 2020 (edited) 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 December 17, 2020 by fabrice montupet 1 Quote Link to comment Share on other sites More sharing options...
+mizapf Posted December 17, 2020 Share Posted December 17, 2020 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? Quote Link to comment Share on other sites More sharing options...
PeteE Posted December 17, 2020 Author Share Posted December 17, 2020 This is the test program I used to verify the timing loop on the hsync. On physical hardware 9918A, it should look like this: 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 2 Quote Link to comment Share on other sites More sharing options...
Tursi Posted December 18, 2020 Share Posted December 18, 2020 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. 4 Quote Link to comment Share on other sites More sharing options...
Tursi Posted December 18, 2020 Share Posted December 18, 2020 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. Quote Link to comment Share on other sites More sharing options...
Tursi Posted December 18, 2020 Share Posted December 18, 2020 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: 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. 2 2 Quote Link to comment Share on other sites More sharing options...
+OLD CS1 Posted December 18, 2020 Share Posted December 18, 2020 17 minutes ago, Tursi said: real hardware which is wrong. My sides. 4 Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted December 18, 2020 Share Posted December 18, 2020 12 hours ago, Tursi said: real hardware which is wrong. Nothing beats emulation ... she said. 2 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.